-
Notifications
You must be signed in to change notification settings - Fork 13.5k
Add BinaryHeap::contains
and BinaryHeap::remove
#82002
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Conversation
r? @m-ou-se (rust-highfive has picked a reviewer for you, use r? to override) |
I think incorrect (or malicious) `PartialEq` and `PartialOrd` implementations for `T` could define `x == y` and `x < y` to both be conditionally true with interior mutability in such a way that `pos == len - 1` (implying `data[pos] == data[len - 1]`) but we end up in the `data[pos] < data[len - 1]` branch. `sift_up()` and `sift_down()` assume that `pos` is in-bounds which would be violated in this case.
Thanks for your PR. I'm afraid that adding these functions will be misleading, as they do nothing special with the structure of a binary heap, making them O(n) just like on a Vec. For For What do you think? |
@m-ou-se I'm mostly interesting interest in the |
Maybe |
@m-ou-se I agree that Initially I had an implementation that used the max-heap property to search for elements as @Thomasdezeeuw suggested but I'm not sure that it's any better than just iterating over the underlying data. The average- and worst-case time complexity is still the same, at least. impl<T: Ord> BinaryHeap<T> {
fn find(&self, item: &T) -> Option<usize> {
self.find_recursive(item, 0)
}
fn find_recursive(&self, item: &T, pos: usize) -> Option<usize> {
if pos >= self.data.len() {
None
} else {
match self.data[pos].cmp(item) {
// If `self.data[pos] == item`, return the item's position.
Ordering::Equal => Some(pos),
// If `self.data[pos] < item`, the item cannot be in either of
// the child branches (because this is a max heap).
Ordering::Less => None,
// If `self.data[pos] > item`, we need to search both child branches.
Ordering::Greater => {
let left_child = 2 * pos + 1;
let right_child = 2 * pos + 2;
self.find_recursive(item, left_child)
.or_else(|| self.find_recursive(item, right_child))
}
}
}
}
} |
This relies on the fact that |
☔ The latest upstream changes (presumably #82756) made this pull request unmergeable. Please resolve the merge conflicts. |
Triage: there's merge conflicts now, and it would be best if you could start a discussion on Zulip to make progress on this. |
@billyrieger ping from triage: can you please fix the merge conflicts? Thank you. |
I'm going to close this - #82331 covers some of the same functionality and at this point it's unclear what the implementation details for |
Tracking issue: #82001.