sorting - How do I create a BinaryHeap that pops the smallest value, not the largest?
问题描述
I can use the std::collections::BinaryHeap
to iterate over a collection of a struct in the greatest to least order with pop
, but my goal is to iterate over the collection from least to greatest.
I have succeeded by reversing the Ord
implementation:
impl Ord for Item {
fn cmp(&self, other: &Self) -> Ordering {
match self.offset {
b if b > other.offset => Ordering::Less,
b if b < other.offset => Ordering::Greater,
b if b == other.offset => Ordering::Equal,
_ => Ordering::Equal, // ?not sure why compiler needs this
}
}
}
Now the BinaryHeap
returns the Item
s in least to greatest. Seeing as how this is not the intended API, is this an incorrect or error prone pattern?
I realize that a LinkedList
would give me the pop_front
method, but I would need to sort the list on insert. Is that the better solution?
解决方案
颠倒堆内类型的顺序很好。但是,您不需要实现自己的订单反转。相反,请酌情使用std::cmp::Reverse
或Ordering::reverse
。
如果当某个字段更大时您的类型实际上小于另一个值是有意义的,请实现您自己的Ord
:
impl Ord for Item {
fn cmp(&self, other: &Self) -> Ordering {
self.offset.cmp(&other.offset).reverse()
}
}
如果您不想更改类型的顺序,请在将其放入时翻转顺序BinaryHeap
:
use std::{cmp::Reverse, collections::BinaryHeap};
fn main() {
let mut a: BinaryHeap<_> = vec![1, 2, 3].into_iter().collect();
if let Some(v) = a.pop() {
println!("Next is {}", v);
}
let mut b: BinaryHeap<_> = vec![1, 2, 3].into_iter().map(Reverse).collect();
if let Some(Reverse(v)) = b.pop() {
println!("Next is {}", v);
}
}
Next is 3
Next is 1
也可以看看:
[a
LinkedList
] 是更好的解决方案吗?
99.9% 的情况下,链表并不是更好的解决方案。
推荐阅读
- json - jsonschema2pojo 生成对象类型的所有变量,但不是我提供的数据类型
- elasticsearch - 为什么 searchResult.TotalHits() 与 len(searchResult.Hits.Hits) 不同?
- java - 从不同的片段访问列表
- pandas - 如何在熊猫列上计算非空值然后聚合
- c# - TFS (AzureDevOps) 2015 C# 获取构建中使用的变量
- node.js - 将 S3 存储桶的内容复制到另一个存储桶 | 节点JS
- angular - 如何在点击时打开弹出窗口?
- c# - 我想在数据表中添加新行而不对现有数据产生任何影响
- string - 如果列表中包含特定单词,如何从列表中删除字符串
- c++11 - 用于 constexpr 深度和 IEEE 754 指数计算的 NVIDIA nvcc 编译标志