我想用浮点数填充二进制堆 - 更具体地说,我想实现一个小堆。
浮动似乎不支持Ord
,因此无法开箱即用。到目前为止,我试图包装它们的尝试失败了。但是,如果我可以将它们包装起来,那么我也可以实现Ord
,以便有效地使BinaryHeap
成为最小堆。
这是我尝试过的包装器的一个例子:
#[derive(PartialEq, PartialOrd)]
struct MinNonNan(f64);
impl Eq for MinNonNan {}
impl Ord for MinNonNan {
fn cmp(&self, other: &MinNonNan) -> Ordering {
let ord = self.partial_cmp(other).unwrap();
match ord {
Ordering::Greater => Ordering::Less,
Ordering::Less => Ordering::Greater,
Ordering::Equal => ord
}
}
}
问题是pop
返回值,就像它是最大堆一样。
我需要做些什么来填充BinaryHeap
f64
值作为最小堆?
答案 0 :(得分:9)
请考虑使用ordered-float crate + std::cmp::Reverse类型,而不是编写自己的MinNonNan
。
type MinNonNan = Reverse<NotNan<f64>>;
由于您#[derive]
PartialOrd
.gt()
,.lt()
,MinNonNan(42.0) < MinNonNan(47.0)
等方法仍然正常比较,即Ord
仍为真。 .cmp()
绑定仅限制您提供严格排序的类型,并不意味着实现将使用<
而不是>
/ <=
/ >=
/ Ord
无处不在,编译器也不会突然改变那些运算符以使用PartialOrd
实现。
如果您想翻转订单,则还需要重新实现#[derive(PartialEq)]
struct MinNonNan(f64);
impl PartialOrd for MinNonNan {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
other.0.partial_cmp(&self.0)
}
}
impl Ord for MinNonNan {
fn cmp(&self, other: &MinNonNan) -> Ordering {
self.partial_cmp(other).unwrap()
}
}
。
search
答案 1 :(得分:5)
use std::cmp::Ordering;
use std::collections::BinaryHeap;
#[derive(PartialEq)]
struct MinFloat(f64);
impl Eq for MinFloat {}
impl PartialOrd for MinFloat {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
other.0.partial_cmp(&self.0)
}
}
impl Ord for MinFloat {
fn cmp(&self, other: &MinFloat) -> Ordering {
self.partial_cmp(other).unwrap()
}
}
fn main() {
let mut minheap = BinaryHeap::new();
minheap.push(MinFloat(2.0));
minheap.push(MinFloat(1.0));
minheap.push(MinFloat(42.0));
if let Some(MinFloat(root)) = minheap.pop() {
println!("{:?}", root);
}
}