-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add BinaryHeap::contains
and BinaryHeap::remove
#82002
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.