如何使用Rust的BinaryHeap实现f64的最小堆?

时间:2016-10-10 00:38:50

标签: rust min-heap

我想用浮点数填充二进制堆 - 更具体地说,我想实现一个小堆。

浮动似乎不支持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值作为最小堆?

2 个答案:

答案 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);
    }
}