How can I implement a min-heap of f64 with Rust's BinaryHeap?

前端 未结 2 1666
旧巷少年郎
旧巷少年郎 2021-01-02 02:15

I want to populate a binary heap with floats--more specifically, I\'d like to implement a min-heap.

It seems that floats do not support Ord and thus are

相关标签:
2条回答
  • 2021-01-02 02:23

    Instead of writing your own MinNonNan, consider using the ordered-float crate + the std::cmp::Reverse type.

    type MinNonNan = Reverse<NotNan<f64>>;
    

    Since you are #[derive]ing PartialOrd, the .gt(), .lt() etc methods still compare normally, i.e. MinNonNan(42.0) < MinNonNan(47.0) is still true. The Ord bound only restricts you to provide strictly-ordered types, it doesn't mean the implementation will use .cmp() instead of </>/<=/>= everywhere, nor the compiler will suddenly change those operators to use the Ord implementation.

    If you want to flip the order, you need to reimplement PartialOrd as well.

    #[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()
        }
    }
    
    0 讨论(0)
  • 2021-01-02 02:25

    Working Example

    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);
        }
    }
    
    0 讨论(0)
提交回复
热议问题