Skip to main content

nekolib/ds/
removable_heap.rs

1//! 削除可能ヒープ。
2
3use std::collections::BinaryHeap;
4
5/// 削除可能ヒープ。
6///
7/// # Idea
8/// ヒープを二つ使う。
9///
10/// # Implementation notes
11/// `peek()` を `&self` にするため、`remove()` と `pop()` の直後はとりあえず
12/// `force()` している。
13///
14/// # Examples
15/// ```
16/// use nekolib::ds::RemovableHeap;
17///
18/// let mut heap = RemovableHeap::new();
19/// heap.push(2);
20/// heap.push(1);
21/// heap.push(3);
22/// heap.push(0);
23/// assert_eq!(heap.peek(), Some(&3)); // {0, 1, 2, 3}
24///
25/// heap.remove(2);                    // {0, 1, 3}
26/// assert_eq!(heap.pop(), Some(3));   // {0, 1}
27/// assert_eq!(heap.peek(), Some(&1));
28/// heap.remove(1);                    // {0}
29/// assert_eq!(heap.peek(), Some(&0));
30/// assert_eq!(heap.pop(), Some(0));   // {}
31/// assert!(heap.is_empty());
32/// ```
33///
34/// 削除する要素がヒープに入っていないとき、こまる。
35/// ```
36/// use nekolib::ds::RemovableHeap;
37///
38/// let mut heap = RemovableHeap::new();
39/// heap.push(1);
40/// heap.remove(2);
41/// heap.push(2);
42/// heap.push(3);                      // {1, 2, 3}?
43/// assert_eq!(heap.pop(), Some(3));   // seems good?
44/// assert_ne!(heap.peek(), Some(&2)); // but...
45/// assert_eq!(heap.peek(), Some(&1));
46/// ```
47///
48/// 未来の push 操作を打ち消すというわけでもない。
49/// ```
50/// use nekolib::ds::RemovableHeap;
51///
52/// let mut heap = RemovableHeap::new();
53/// heap.push(1);
54/// heap.push(2);
55/// heap.remove(100);
56/// heap.remove(3);
57/// heap.push(101);
58/// heap.push(3);                      // {1, 2, 101}?
59/// assert_eq!(heap.pop(), Some(101)); // seems good, so far
60/// assert_ne!(heap.peek(), Some(&2)); // but...
61/// assert_eq!(heap.peek(), Some(&3));
62/// ```
63#[derive(Clone)]
64pub struct RemovableHeap<T> {
65    alive: BinaryHeap<T>,
66    dead: BinaryHeap<T>,
67    len: usize,
68}
69
70impl<T: Ord> RemovableHeap<T> {
71    /// 空のヒープで初期化する。
72    pub fn new() -> Self {
73        Self {
74            alive: BinaryHeap::new(),
75            dead: BinaryHeap::new(),
76            len: 0,
77        }
78    }
79
80    /// 要素を追加する。
81    pub fn push(&mut self, item: T) {
82        self.len += 1;
83        self.alive.push(item);
84    }
85
86    /// 要素を削除する。
87    ///
88    /// # Notes
89    /// 削除処理を遅延させて行うため、`&T` ではなく `T` であることに注意。
90    ///
91    /// また、`item` はその時点でヒープに入っている要素のいずれかと等しい必要がある。
92    /// 「未来に追加される要素を打ち消す」あるいは「単に無視する」という仕様は、
93    /// どちらも操作順しだいでどちらもうまくいかなくなるはず。
94    ///
95    /// `BTreeSet` を使えば判定できるが、それなら最初から `BTreeSet` でやればよい。
96    pub fn remove(&mut self, item: T) {
97        self.len -= 1;
98        self.dead.push(item);
99        self.force();
100    }
101
102    /// 最大値を取り出す。
103    pub fn pop(&mut self) -> Option<T> {
104        self.force();
105        let res = self.alive.pop();
106        if res.is_some() {
107            self.len -= 1;
108            self.force();
109        }
110        res
111    }
112
113    /// 最大値を取得する。
114    pub fn peek(&self) -> Option<&T> { self.alive.peek() }
115
116    /// 空のとき `true` を返す。
117    pub fn is_empty(&self) -> bool { self.len == 0 }
118
119    /// 要素数を返す。
120    pub fn len(&self) -> usize { self.len }
121
122    fn force(&mut self) {
123        while let (Some(x), Some(y)) = (self.alive.peek(), self.dead.peek()) {
124            if x != y {
125                break;
126            }
127            self.alive.pop();
128            self.dead.pop();
129        }
130    }
131}
132
133#[test]
134fn test() {
135    let mut heap = RemovableHeap::new();
136    assert_eq!(heap.pop(), None);
137    heap.push(1); // {1}
138    assert_eq!(heap.peek(), Some(&1));
139    assert_eq!(heap.len(), 1);
140    heap.push(2); // {1, 2}
141    assert_eq!(heap.peek(), Some(&2));
142    assert_eq!(heap.len(), 2);
143    heap.remove(1); // {2}
144    assert_eq!(heap.len(), 1);
145    assert_eq!(heap.pop(), Some(2)); // {}
146    assert_eq!(heap.len(), 0);
147    assert_eq!(heap.pop(), None); // {}
148    assert_eq!(heap.len(), 0);
149
150    heap.push(2); // {2}
151    heap.push(1); // {1, 2}
152    assert_eq!(heap.len(), 2);
153    heap.remove(2); // {1}
154    assert_eq!(heap.len(), 1);
155    assert_eq!(heap.pop(), Some(1)); // {}
156    assert_eq!(heap.len(), 0);
157}