]> git.lizzy.rs Git - rust.git/commitdiff
Add PeekMut::pop
authorSteven Fackler <sfackler@gmail.com>
Sat, 31 Dec 2016 05:18:17 +0000 (21:18 -0800)
committerSteven Fackler <sfackler@gmail.com>
Mon, 2 Jan 2017 03:18:07 +0000 (19:18 -0800)
A fairly common workflow is to put a bunch of stuff into a binary heap
and then mutate the top value until its empty. This both makes that a
bit more convenient (no need to save a boolean off and pop after to
avoid borrowck issues), and a bit more efficient since you only shift
once.

src/libcollections/binary_heap.rs
src/libcollectionstest/binary_heap.rs
src/libcollectionstest/lib.rs

index c5d5ad27d2304923dc51aa9196933c78072475b6..c53b34d589bd0fc6d686cf7b002a0a1f43b81413 100644 (file)
 
 use core::ops::{Deref, DerefMut};
 use core::iter::{FromIterator, FusedIterator};
-use core::mem::swap;
-use core::mem::size_of;
+use core::mem::{swap, size_of};
 use core::ptr;
 use core::fmt;
 
@@ -226,12 +225,15 @@ pub struct BinaryHeap<T> {
 #[stable(feature = "binary_heap_peek_mut", since = "1.12.0")]
 pub struct PeekMut<'a, T: 'a + Ord> {
     heap: &'a mut BinaryHeap<T>,
+    sift: bool,
 }
 
 #[stable(feature = "binary_heap_peek_mut", since = "1.12.0")]
 impl<'a, T: Ord> Drop for PeekMut<'a, T> {
     fn drop(&mut self) {
-        self.heap.sift_down(0);
+        if self.sift {
+            self.heap.sift_down(0);
+        }
     }
 }
 
@@ -250,6 +252,16 @@ fn deref_mut(&mut self) -> &mut T {
     }
 }
 
+impl<'a, T: Ord> PeekMut<'a, T> {
+    /// Removes the peeked value from the heap and returns it.
+    #[unstable(feature = "binary_heap_peek_mut_pop", issue = "0")]
+    pub fn pop(mut this: PeekMut<'a, T>) -> T {
+        let value = this.heap.pop().unwrap();
+        this.sift = false;
+        value
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Clone> Clone for BinaryHeap<T> {
     fn clone(&self) -> Self {
@@ -385,7 +397,10 @@ pub fn peek_mut(&mut self) -> Option<PeekMut<T>> {
         if self.is_empty() {
             None
         } else {
-            Some(PeekMut { heap: self })
+            Some(PeekMut {
+                heap: self,
+                sift: true,
+            })
         }
     }
 
index 9cd63d87931842caf06b546bdbca546c54d40fe0..1df341d1fc28a1e35dcd5ab36e89d0002b2db559 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use std::collections::BinaryHeap;
-use std::collections::binary_heap::Drain;
+use std::collections::binary_heap::{Drain, PeekMut};
 
 #[test]
 fn test_iterator() {
@@ -94,6 +94,19 @@ fn test_peek_mut() {
     assert_eq!(heap.peek(), Some(&9));
 }
 
+#[test]
+fn test_peek_mut_pop() {
+    let data = vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1];
+    let mut heap = BinaryHeap::from(data);
+    assert_eq!(heap.peek(), Some(&10));
+    {
+        let mut top = heap.peek_mut().unwrap();
+        *top -= 2;
+        assert_eq!(PeekMut::pop(top), 8);
+    }
+    assert_eq!(heap.peek(), Some(&9));
+}
+
 #[test]
 fn test_push() {
     let mut heap = BinaryHeap::from(vec![2, 4, 9]);
index d4fb5ea03adea50071566bff326a29e763fee87a..ee555ee351ed9c0f005498abb261332579b89c97 100644 (file)
@@ -11,6 +11,7 @@
 #![deny(warnings)]
 
 #![feature(binary_heap_extras)]
+#![feature(binary_heap_peek_mut_pop)]
 #![feature(box_syntax)]
 #![feature(btree_range)]
 #![feature(collections)]