pheap/
ph.rs

1use std::{collections::VecDeque, ops::SubAssign, ptr::NonNull};
2
3/// A min-pairing heap data structure.
4#[derive(Debug)]
5pub struct PairingHeap<K, P> {
6    root: Option<NonNull<Inner<K, P>>>,
7    len: usize,
8}
9
10impl<K, P> PairingHeap<K, P> {
11    /// Creates an empty pairing heap.
12    #[inline]
13    pub fn new() -> Self {
14        Self::default()
15    }
16
17    /// Returns the number of elements stored in the heap.
18    #[inline]
19    pub fn len(&self) -> usize {
20        self.len
21    }
22
23    /// Checks whether the heap is empty.
24    #[inline]
25    pub fn is_empty(&self) -> bool {
26        self.len == 0
27    }
28
29    /// Returns the minimum element, which is the root element, and its priority in a tuple of the heap.
30    #[inline]
31    pub fn find_min(&self) -> Option<(&K, &P)> {
32        match self.root {
33            Some(node) => unsafe {
34                let r = node.as_ref();
35                Some((&r.key, &r.prio))
36            },
37            None => None,
38        }
39    }
40
41    /// Merges two heaps together and forms a new heap.
42    ///
43    /// If one heap is empty, the other heap will be returned and vice versa. Otherwise, a new heap
44    /// will be created, whose root is the root that has a smaller value. The other root will be
45    /// inserted in the new heap.
46    #[inline]
47    pub fn merge(mut self, mut other: Self) -> Self
48    where
49        P: PartialOrd,
50    {
51        let len = self.len() + other.len();
52        let root = Self::merge_nodes(self.root, other.root);
53
54        self.root = None;
55        other.root = None;
56
57        Self { root, len }
58    }
59
60    #[inline]
61    fn merge_nodes(
62        node1: Option<NonNull<Inner<K, P>>>,
63        node2: Option<NonNull<Inner<K, P>>>,
64    ) -> Option<NonNull<Inner<K, P>>>
65    where
66        P: PartialOrd,
67    {
68        match (node1, node2) {
69            (Some(root1), Some(root2)) => unsafe {
70                let root = if root1.as_ref().prio < root2.as_ref().prio {
71                    Self::meld(root1, root2)
72                } else {
73                    Self::meld(root2, root1)
74                };
75                Some(root)
76            },
77            (Some(_), None) => node1,
78            (None, Some(_)) => node2,
79            _ => node1,
80        }
81    }
82
83    #[inline(always)]
84    unsafe fn meld(
85        node1: NonNull<Inner<K, P>>,
86        node2: NonNull<Inner<K, P>>,
87    ) -> NonNull<Inner<K, P>> {
88        (*node2.as_ptr()).parent = Some(node1);
89        (*node2.as_ptr()).right = node1.as_ref().left;
90        (*node1.as_ptr()).left = Some(node2);
91        node1
92    }
93
94    /// Inserts a new element to the heap.
95    #[inline]
96    pub fn insert(&mut self, key: K, prio: P)
97    where
98        P: PartialOrd,
99    {
100        self.insert2(key, prio);
101    }
102
103    // Expose HeapElmt to pub, no?
104    #[inline]
105    pub(crate) fn insert2(&mut self, key: K, prio: P) -> HeapElmt<K, P>
106    where
107        P: PartialOrd,
108    {
109        let node = NonNull::new(Box::leak(Box::new(Inner::new(key, prio))));
110
111        self.root = Self::merge_nodes(self.root, node);
112        self.len += 1;
113
114        HeapElmt { inner: node }
115    }
116
117    /// Decreases the priority of a key by the amount given in ```delta```.
118    pub fn decrease_prio(&mut self, key: &K, delta: P)
119    where
120        K: PartialEq,
121        P: PartialOrd + SubAssign,
122    {
123        if let Some(root) = self.root {
124            unsafe {
125                if &root.as_ref().key == key {
126                    (*root.as_ptr()).prio -= delta;
127                    return;
128                }
129
130                let mut targ = None;
131                let mut prev = None;
132                let mut tmp_nodes = VecDeque::with_capacity(self.len << 2);
133                let mut traverse = root.as_ref().left;
134
135                while let Some(node) = traverse {
136                    if &node.as_ref().key == key {
137                        targ = traverse;
138                        break;
139                    }
140
141                    prev = traverse;
142                    tmp_nodes.push_back(traverse);
143
144                    if node.as_ref().right.is_some() {
145                        traverse = node.as_ref().right;
146                    } else {
147                        while let Some(front) = tmp_nodes.pop_front() {
148                            traverse = front.unwrap().as_ref().left;
149                            if traverse.is_some() {
150                                break;
151                            }
152                        }
153                    }
154                }
155
156                if let Some(node) = targ {
157                    // Every node must have a parent. So unwrap() here shouldn't panic.
158                    let parent = node.as_ref().parent.unwrap();
159                    (*node.as_ptr()).prio -= delta;
160
161                    if parent.as_ref().prio < node.as_ref().prio {
162                        return;
163                    }
164
165                    if parent.as_ref().left == targ {
166                        (*parent.as_ptr()).left = node.as_ref().right;
167                    }
168
169                    if let Some(prev_node) = prev {
170                        if prev_node.as_ref().right == targ {
171                            (*prev_node.as_ptr()).right = node.as_ref().right;
172                        }
173                    }
174
175                    (*node.as_ptr()).parent = None;
176                    (*node.as_ptr()).right = None;
177
178                    self.root = Self::merge_nodes(self.root, targ);
179                }
180            }
181        }
182    }
183
184    // TODO: currently only works when new_prio < prio.
185    pub(crate) fn update_prio(&mut self, node: &HeapElmt<K, P>, new_prio: P)
186    where
187        P: PartialOrd,
188    {
189        unsafe {
190            self.update(node.inner, new_prio);
191        }
192    }
193
194    unsafe fn update(&mut self, targ: Option<NonNull<Inner<K, P>>>, new_prio: P)
195    where
196        P: PartialOrd,
197    {
198        if let Some(node) = targ {
199            match node.as_ref().parent {
200                Some(parent) => {
201                    let mut prev = parent.as_ref().left;
202
203                    while let Some(prev_node) = prev {
204                        if prev_node.as_ref().right == targ {
205                            break;
206                        } else {
207                            prev = prev_node.as_ref().right;
208                        }
209                    }
210
211                    (*node.as_ptr()).prio = new_prio;
212
213                    if parent.as_ref().prio < node.as_ref().prio {
214                        return;
215                    }
216
217                    if parent.as_ref().left == targ {
218                        (*parent.as_ptr()).left = node.as_ref().right;
219                    }
220
221                    if let Some(prev_node) = prev {
222                        if prev_node.as_ref().right == targ {
223                            (*prev_node.as_ptr()).right = node.as_ref().right;
224                        }
225                    }
226
227                    (*node.as_ptr()).parent = None;
228                    (*node.as_ptr()).right = None;
229
230                    self.root = Self::merge_nodes(self.root, targ);
231                }
232                None => {
233                    (*node.as_ptr()).prio = new_prio;
234                }
235            };
236        }
237    }
238
239    /// Deletes the minimum element, which is the root, of the heap, and then returns the root's key value and priority.
240    pub fn delete_min(&mut self) -> Option<(K, P)>
241    where
242        P: PartialOrd,
243    {
244        self.root.map(|root| unsafe {
245            self.len -= 1;
246            let mut targ = (*root.as_ptr()).left.take();
247            if targ.is_none() {
248                self.root = None;
249            } else {
250                // TODO: optimise so that capacity is known here.
251                let mut tmp_nodes = VecDeque::new();
252
253                // First pass: left to right
254                while let Some(node) = targ {
255                    (*node.as_ptr()).parent = None;
256                    let right = (*node.as_ptr()).right.take();
257
258                    let node_next = match right {
259                        Some(node_right) => {
260                            let next = (*node_right.as_ptr()).right.take();
261                            (*node_right.as_ptr()).parent = None;
262                            next
263                        }
264                        None => None,
265                    };
266
267                    tmp_nodes.push_back(Self::merge_nodes(Some(node), right));
268
269                    targ = node_next;
270                }
271
272                // Second pass: right to left
273                // If left is not None, there must be at least one element in VecDeque.
274                // So unwrap() is safe here.
275                let mut node = tmp_nodes.pop_back().unwrap();
276
277                while let Some(node_prev) = tmp_nodes.pop_back() {
278                    node = Self::merge_nodes(node, node_prev);
279                }
280
281                self.root = node;
282            }
283            let node = Box::from_raw(root.as_ptr());
284            node.into_value()
285        })
286    }
287}
288
289impl<K, P> Default for PairingHeap<K, P> {
290    fn default() -> Self {
291        Self { root: None, len: 0 }
292    }
293}
294
295impl<K, P> Drop for PairingHeap<K, P> {
296    fn drop(&mut self) {
297        // Remove all children of a node, then the node itself.
298        // Returns the next sibling in the end.
299
300        unsafe fn remove<K, P>(targ: Option<NonNull<Inner<K, P>>>) -> Option<NonNull<Inner<K, P>>> {
301            if let Some(node) = targ {
302                while let Some(left) = node.as_ref().left {
303                    (*node.as_ptr()).left = remove(Some(left));
304                }
305
306                let sibling = (*node.as_ptr()).right.take();
307                (*node.as_ptr()).parent = None;
308                Box::from_raw(node.as_ptr());
309
310                sibling
311            } else {
312                None
313            }
314        }
315
316        unsafe {
317            remove(self.root);
318        }
319
320        self.root = None;
321    }
322}
323
324#[derive(Clone, Debug)]
325pub(crate) struct HeapElmt<K, P> {
326    inner: Option<NonNull<Inner<K, P>>>,
327}
328
329impl<K, P> HeapElmt<K, P> {
330    pub(crate) fn is_none(&self) -> bool {
331        self.inner.is_none()
332    }
333
334    pub(crate) fn none(&mut self) {
335        self.inner = None;
336    }
337}
338
339impl<K, P> Default for HeapElmt<K, P> {
340    fn default() -> Self {
341        Self { inner: None }
342    }
343}
344
345#[derive(Debug)]
346struct Inner<K, P> {
347    /// Pointer to a node's parent.
348    parent: Option<NonNull<Inner<K, P>>>,
349    /// Pointer to a node's first (or left-most) child.
350    left: Option<NonNull<Inner<K, P>>>,
351    /// Pointer to a node's next older sibling.
352    right: Option<NonNull<Inner<K, P>>>,
353    key: K,
354    prio: P,
355}
356
357impl<K, P> Inner<K, P> {
358    fn new(key: K, prio: P) -> Self {
359        Self {
360            key,
361            prio,
362            parent: None,
363            left: None,
364            right: None,
365        }
366    }
367
368    fn into_value(self) -> (K, P) {
369        (self.key, self.prio)
370    }
371}