Skip to content

Add BinaryHeap::retain#668

Open
Conaclos wants to merge 4 commits into
rust-embedded:mainfrom
Conaclos:binaryheap_retain
Open

Add BinaryHeap::retain#668
Conaclos wants to merge 4 commits into
rust-embedded:mainfrom
Conaclos:binaryheap_retain

Conversation

@Conaclos

@Conaclos Conaclos commented Jul 8, 2026

Copy link
Copy Markdown

Implement #666

This PR adds the BinaryHeap::retain method.
I didn't base my work on #345 because the implementation seems wrong to me.

I added an internal method BinaryHeap::remove that is now used by both BinaryHeap::retain and BinaryHeap::pop_unchecked.
In the process I improved its implementation.

One alternative implementation could be to traverse the internal vector in reverse order. This could reduce the number of shifted elements if retain removes multiple elements. However, this would make the implementation much more complex.

@Conaclos Conaclos changed the title Add BinaryHeap::retain Add BinaryHeap::retain Jul 8, 2026
@Conaclos
Conaclos force-pushed the binaryheap_retain branch 4 times, most recently from 87e788b to 64e77df Compare July 8, 2026 15:17
@zeenix

zeenix commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

I didn't base my work on #345 because the implementation seems wrong to me.

How so?

@Conaclos

Conaclos commented Jul 8, 2026

Copy link
Copy Markdown
Author

How so?

The implementation doesn't preserve the order invariant of the binary heap.
For example, if you take the binary max-heap [8, 2, 5] and ask to retain only the numbers that are different of 8, then you end up with [2, 5], which is incorrect.

@zeenix

zeenix commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

For example, if you take the binary max-heap [8, 2, 5] and ask to retain only the numbers that are different of 8, then you end up with [2, 5], which is incorrect.

Huh? Is it? 🤔 https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=98dfdde25b2a102d7146761f6d5294db

@Conaclos

Conaclos commented Jul 8, 2026

Copy link
Copy Markdown
Author

I will add some tests for sift_down_to_bottom because the function seems untested with arguments (pos) greater than 0.

@Conaclos

Conaclos commented Jul 8, 2026

Copy link
Copy Markdown
Author

Huh? Is it? 🤔 https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=98dfdde25b2a102d7146761f6d5294db

Your example is wrong because you called into_sorted_vec() in the assertion. It will always return [2, 5].
Instead, try: https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=dccba979ca3526f18a2a2dea5f93130f

@zeenix

zeenix commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Your example is wrong because you called into_sorted_vec() in the assertion. It will always return [2, 5].
Instead, try: https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=dccba979ca3526f18a2a2dea5f93130f

Ah right. That was from the std doc example I started off from.

@Conaclos
Conaclos force-pushed the binaryheap_retain branch 3 times, most recently from 4c41991 to d8e3a5c Compare July 21, 2026 20:02
@Conaclos
Conaclos force-pushed the binaryheap_retain branch from 985fee8 to beb1189 Compare July 21, 2026 20:10
@Conaclos
Conaclos force-pushed the binaryheap_retain branch 2 times, most recently from 58678fe to 1535316 Compare July 21, 2026 20:12
@Conaclos

Copy link
Copy Markdown
Author

Ready for review!

@zeenix zeenix left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only tiny nits and then it's good from my side.

Comment thread CHANGELOG.md

- Added `resize_with` to `Vec`
- Added `retain_back` (aka `truncate_front`) to `Deque`
- Added `retain` to `BinaryHeap`

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing .. I know the previous entries did the same but let's not perpetuate this. :) Feel free to add to them too.

Comment thread src/binary_heap.rs
/* Private API */

/// Removes and returns the element at position `index` within the inner vec.
/// The elements are shifted to preserve the invariants of the binary heap.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's follow the Rust convention: title + empty line and then explanation etc in the next paragraph:

Suggested change
/// The elements are shifted to preserve the invariants of the binary heap.
///
/// The elements are shifted to preserve the invariants of the binary heap.

Comment thread src/binary_heap.rs
mem::swap(&mut item, self.data.as_mut_slice().get_unchecked_mut(0));
self.sift_down_to_bottom(0);
/// Retains only the elements specified by the predicate.
/// The elements are visited in arbitrary order.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// The elements are visited in arbitrary order.
///
/// The elements are visited in arbitrary order.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants