-
Notifications
You must be signed in to change notification settings - Fork 13.8k
Implement placement-in protocol for BinaryHeap
#39062
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
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -151,7 +151,7 @@ | |
#![allow(missing_docs)] | ||
#![stable(feature = "rust1", since = "1.0.0")] | ||
|
||
use core::ops::{Deref, DerefMut}; | ||
use core::ops::{Deref, DerefMut, Place, Placer, InPlace}; | ||
use core::iter::{FromIterator, FusedIterator}; | ||
use core::mem::{swap, size_of}; | ||
use core::ptr; | ||
|
@@ -688,6 +688,22 @@ impl<T: Ord> BinaryHeap<T> { | |
} | ||
} | ||
|
||
fn sift_up_ind(&mut self, start: usize, pos: usize) -> usize { | ||
unsafe { | ||
// Take out the value at `pos` and create a hole. | ||
let mut hole = Hole::new(&mut self.data, pos); | ||
|
||
while hole.pos() > start { | ||
let parent = (hole.pos() - 1) / 2; | ||
if hole.element() <= hole.get(parent) { | ||
return hole.pos(); | ||
} | ||
hole.move_to(parent); | ||
} | ||
hole.pos() | ||
} | ||
} | ||
|
||
/// Take an element at `pos` and move it down the heap, | ||
/// while its children are larger. | ||
fn sift_down_range(&mut self, pos: usize, end: usize) { | ||
|
@@ -889,6 +905,19 @@ impl<T: Ord> BinaryHeap<T> { | |
} | ||
} | ||
|
||
impl<T> BinaryHeap<T> | ||
where T: Clone + Ord { | ||
/// kek | ||
#[unstable(feature = "collection_placement", | ||
reason = "placement protocol is subject to change", | ||
issue = "30172")] | ||
pub fn place(&mut self) -> PlaceIn<T> { | ||
PlaceIn { | ||
heap: self, | ||
} | ||
} | ||
} | ||
|
||
/// Hole represents a hole in a slice i.e. an index without valid value | ||
/// (because it was moved from or duplicated). | ||
/// In drop, `Hole` will restore the slice by filling the hole | ||
|
@@ -1189,3 +1218,49 @@ impl<'a, T: 'a + Ord + Copy> Extend<&'a T> for BinaryHeap<T> { | |
self.extend(iter.into_iter().cloned()); | ||
} | ||
} | ||
|
||
#[unstable(feature = "collection_placement", | ||
reason = "placement protocol is subject to change", | ||
issue = "30172")] | ||
pub struct PlaceIn<'a, T: 'a> | ||
where T: Clone + Ord { | ||
heap: &'a mut BinaryHeap<T>, | ||
} | ||
|
||
#[unstable(feature = "collection_placement", | ||
reason = "placement protocol is subject to change", | ||
issue = "30172")] | ||
impl<'a, T> Place<T> for PlaceIn<'a, T> | ||
where T: Clone + Ord { | ||
fn pointer(&mut self) -> *mut T { | ||
self.heap.data.place_back().pointer() | ||
|
||
} | ||
} | ||
|
||
#[unstable(feature = "collection_placement", | ||
reason = "placement protocol is subject to change", | ||
issue = "30172")] | ||
impl<'a, T> Placer<T> for PlaceIn<'a, T> | ||
where T: Clone + Ord { | ||
type Place = PlaceIn<'a, T>; | ||
|
||
fn make_place(self) -> Self { | ||
let _ = self.heap.data.place_back().make_place(); | ||
self | ||
|
||
} | ||
} | ||
|
||
#[unstable(feature = "collection_placement", | ||
reason = "placement protocol is subject to change", | ||
issue = "30172")] | ||
impl<'a, T> InPlace<T> for PlaceIn<'a, T> | ||
where T: Clone + Ord { | ||
type Owner = &'a T; | ||
|
||
unsafe fn finalize(self) -> &'a T { | ||
let len = self.heap.len(); | ||
let _ = self.heap.data.place_back().finalize(); | ||
let i = self.heap.sift_up_ind(0, len); | ||
&mut self.heap.data[i] | ||
|
||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can simply adjust the
sift_up
to return the index, since its a private implementation detail and will also avoid the code duplication.