1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
pub mod fibonacci_heap { fn store_to_map<T, F>( map: &mut std::collections::HashMap<usize, Node<T>>, mut node: Node<T>, ordering: F, ) where T: Copy + PartialEq, F: Fn(T, T) -> T, { let d = node.children.len(); match map.remove(&d) { Some(mut other) => { let node = if (ordering)(node.key, other.key) == node.key { node.children.push(other); node } else { other.children.push(node); other }; store_to_map(map, node, ordering); } None => { map.insert(d, node); } } } pub struct FibonacciHeap<T, F> { pub nodes: Vec<Node<T>>, min_index: usize, ordering: F, } impl<T, F> FibonacciHeap<T, F> where T: Copy + PartialEq, F: Fn(T, T) -> T + Copy, { pub fn new(ordering: F) -> Self { Self { nodes: Vec::new(), min_index: 0, ordering: ordering, } } pub fn push(&mut self, x: T) { let node = Node::new(x); self.nodes.push(node); let cur_min = self.nodes[self.min_index].key; if (self.ordering)(cur_min, x) == x { self.min_index = self.nodes.len() - 1; } } pub fn pop(&mut self) -> Option<T> { let mut map = std::collections::HashMap::<usize, Node<T>>::new(); let mut popped = None; let mut nodes = Vec::new(); std::mem::swap(&mut self.nodes, &mut nodes); for (i, node) in nodes.into_iter().enumerate() { if i == self.min_index { popped = Some(node.key); for node in node.children.into_iter() { store_to_map(&mut map, node, self.ordering); } } else { store_to_map(&mut map, node, self.ordering); } } self.nodes = map.into_iter().map(|(_, node)| node).collect(); if !self.nodes.is_empty() { let mut min = self.nodes[0].key; for i in 0..self.nodes.len() { if (self.ordering)(min, self.nodes[i].key) == self.nodes[i].key { min = self.nodes[i].key; } } self.min_index = self .nodes .iter() .enumerate() .find(|(_, node)| node.key == min) .unwrap() .0; } else { self.min_index = 0; } popped } } #[derive(Debug)] pub struct Node<T> { pub key: T, pub children: Vec<Node<T>>, } impl<T> Node<T> { fn new(x: T) -> Self { Self { key: x, children: Vec::new(), } } } } #[cfg(test)] mod tests { use super::fibonacci_heap::*; use rand::Rng; use std::cmp; use std::collections::BinaryHeap; #[test] fn test_fibonacci_heap() { let mut min_heap = FibonacciHeap::new(cmp::min); min_heap.push(1); assert_eq!(min_heap.pop(), Some(1)); min_heap.push(1); min_heap.push(2); min_heap.push(3); assert_eq!(min_heap.pop(), Some(1)); assert_eq!(min_heap.pop(), Some(2)); assert_eq!(min_heap.pop(), Some(3)); min_heap.push(3); min_heap.push(2); min_heap.push(1); assert_eq!(min_heap.pop(), Some(1)); assert_eq!(min_heap.pop(), Some(2)); assert_eq!(min_heap.pop(), Some(3)); } #[test] fn compare_to_binary_heap() { let mut rng = rand::thread_rng(); let mut max_heap = FibonacciHeap::new(cmp::max); let mut binary_heap = BinaryHeap::new(); for _ in 0..2000 { let x = rng.gen::<usize>() % 10; if x == 0 { assert_eq!(max_heap.pop(), binary_heap.pop()); } else { let v = rng.gen::<u8>(); max_heap.push(v); binary_heap.push(v); } } } }