I am using the standard BinaryHeap as part of an algorithm where I need to retrieve the largest object (via some definition of largest). It could be possible that two non-equivalent elements are both equally large (and hence their relative order in the binary heap does not matter) - for example, I might be only interested in sorting on a single field of a multi-field struct.
Because of this, it would be somewhat unusual to have my type implement Ord and Eq. Instead, I should probably implement PartialOrd and PartialEq only. But, alas, BinaryHeap requires its elements to be Ord! Why is this so, and what is the most idiomatic way to use BinaryHeap with such types?
(As an aside, in C++, I would fairly easily write a custom comparator type in such a situation, and template the priority queue on the comparator type. So I don't think what I want to do is mathematically or algorithmically wrong.)
PartialOrdgives you asymmetric and transitive ordering, that isa < bimplies!(a > b)anda < b && b < cimpliesa < c.PartialOrddoes not require for all elements to actually have a meaningful ordering at all, which is whyPartialOrd::partial_cmpreturns anOption<Ordering>whereNonemeans "I don't know" (notice that this does not impair the aforementioned requirements).A binary heap requires total ordering for its elements, however, because a binary heap has to have the property that "the key stored in each node is either greater than or equal to (≥) or less than or equal to (≤) the keys in the node's children, according to some total order." (direct quote via Wikipedia).
Only
Ordgives you asymmetric, transitive and total (exactly one ofa < b,a == bora > b) ordering. The requirement for total order leads toOrd::cmpreturning aOrdering, not aOption<Ordering>, because theNone-case is not allowed.It is not uncommon the write specific implementations of
PartialOrdandOrdin case you need specific behaviour. There is also theeducecrate, which allows you to derive a more specific version ofPartialOrdandOrdwhere certain fields are ignored.