Rust二叉堆或优先队列在具有两种排序方式的结构上

huangapple go评论69阅读模式
英文:

Rust binary-heap or priority queue on struct with 2 ways to order

问题

pub struct Dog {
    pub age: u32,
    pub weight: u32,
}
impl Dog {
    pub fn new(age: u32, weight: u32) -> Self {
        Self {
            age: age,
            weight: weight,
        }
    }
}

// For age-based priority queue
use std::collections::BinaryHeap;
impl Ord for Dog {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        self.age.cmp(&other.age).reverse()
    }
}
impl PartialOrd for Dog {
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        Some(self.cmp(other))
    }
}

let mut age_heap: BinaryHeap<Dog> = BinaryHeap::new();
age_heap.push(Dog::new(1, 3));
age_heap.push(Dog::new(2, 2));
age_heap.push(Dog::new(3, 1));

// For weight-based priority queue
use std::collections::BinaryHeap;
impl Ord for Dog {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        self.weight.cmp(&other.weight).reverse()
    }
}
impl PartialOrd for Dog {
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        Some(self.cmp(other))
    }
}

let mut weight_heap: BinaryHeap<Dog> = BinaryHeap::new();
weight_heap.push(Dog::new(1, 3));
weight_heap.push(Dog::new(2, 2));
weight_heap.push(Dog::new(3, 1));
英文:

I'm new to Rust, and I want to implement something similar to a priority queue with a custom comparator like in Java.

Say I have a struct like this:

pub struct Dog {
    pub age:    u32,
    pub weight:  u32,
}
impl Dog {
    pub fn new(age: u32, weight: u32) -&gt; Self {
        Self {
            age: age,
            weight: weight,
        }
    }
}

How do I implement 2 different priority queues or binary heaps that are able to order just based on one of the attributes, like say an ageHeap and a weightHeap.

Say I have something like this

let d1 = Dog::new(1,3);
let d2 = Dog::new(2,2);
let d3 = Dog::new(3,1);

If I pass into the ageHeap, when popping, I would get d1,d2,d3. If I pass into the weightHeap, when popping, I would get d3,d2,d1.

答案1

得分: 2

标准库 BinaryHeap 使用存储类型的 Ord 作为其比较器,因此无法为单个类型更改它。您可以为要使用的每个额外比较器创建一个包装类型。

#[derive(PartialEq, Eq)]
pub struct WeightDog(pub Dog);

impl Ord for WeightDog {
    fn cmp(&amp;self, other: &amp;Self) -&gt; std::cmp::Ordering {
        self.0
            .weight
            .cmp(&amp;other.0.weight)
            .then_with(|| self.0.age.cmp(&amp;other.0.age))
    }
}

impl PartialOrd for WeightDog {
    fn partial_cmp(&amp;self, other: &amp;Self) -&gt; Option&lt;std::cmp::Ordering&gt; {
        Some(self.cmp(other))
    }
}

您还可以创建一个二进制堆类型,并在其构造函数中传入比较器。这就是 binary-heap-plus crate 所做的。

let comparator = binary_heap_plus::KeyComparator(|dog: &amp;Dog| (dog.weight, dog.age));
let mut heap = binary_heap_plus::BinaryHeap::from_vec_cmp(vec![d1, d2, d3], comparator);

标准库的堆和 binary-heap-plus 的堆都是最大堆,因此它们将以与您指定的相反顺序弹出项目。您可以为最小堆使用不同的比较器,或者将您的比较器包装在 Rev 中。

英文:

The standard library BinaryHeap uses the stored type's Ord as its comparator, so you can't change it for a single type. You can create a wrapper type for each additional comparator you want to use.

#[derive(PartialEq, Eq)]
pub struct WeightDog(pub Dog);

impl Ord for WeightDog {
    fn cmp(&amp;self, other: &amp;Self) -&gt; std::cmp::Ordering {
        self.0
            .weight
            .cmp(&amp;other.0.weight)
            .then_with(|| self.0.age.cmp(&amp;other.0.age))
    }
}

impl PartialOrd for WeightDog {
    fn partial_cmp(&amp;self, other: &amp;Self) -&gt; Option&lt;std::cmp::Ordering&gt; {
        Some(self.cmp(other))
    }
}

You can also create a binary heap type that takes a comparator in its constructor. This is what the binary-heap-plus crate does.

let comparator = binary_heap_plus::KeyComparator(|dog: &amp;Dog| (dog.weight, dog.age));
let mut heap = binary_heap_plus::BinaryHeap::from_vec_cmp(vec![d1, d2, d3], comparator);

Both the standard library's heap and binary-heap-plus's heap are max-heaps, so these will pop items in the opposite order than what you specified. You can use a different comparator for a min-heap, or wrap your comparator in Rev.

huangapple
  • 本文由 发表于 2023年5月15日 03:35:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/76249349.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定