rusty_structures/priority_queue/
dheap.rs

1use std::fmt::Display;
2
3use crate::priority_queue::pair::Pair;
4
5#[derive(Debug)]
6pub struct DHeap<T: Clone + Display + PartialEq> {
7    data: Vec<Pair<T>>,
8    branching_factor: usize
9}
10
11impl<T: Clone + Display + PartialEq> DHeap<T> {
12    pub fn new(initial_capacity: Option<usize>, branching_factor: Option<usize>) -> Self {
13        match initial_capacity {
14            Some(v) => DHeap { data: Vec::with_capacity(v), 
15                branching_factor: branching_factor.unwrap_or(2)},
16            None => DHeap { data: Vec::new(),
17                branching_factor: branching_factor.unwrap_or(2)},
18        }
19    }
20
21    pub fn heapify(&mut self)
22    {
23        let mut max_index = (self.data.len() - 1) / self.branching_factor;
24        while max_index != 0 {
25            self.push_down_optimized(Some(max_index));
26            max_index -= 1;
27        }
28    }
29
30    pub fn insert(&mut self, element: Pair<T>) {
31        self.data.push(element);
32        self.bubble_up(None);
33    }
34
35    pub fn peek(&self) -> Option<&Pair<T>> {
36        if self.data.len() == 0 {
37            None
38        } else {
39            Some(&self.data[0])
40        }
41    }
42
43    pub fn update_priority(&mut self, old_value: T, new_priority: usize) {
44        if let Some(index) = self.find_index(old_value) {
45            let temp = self.data[index].clone();
46            self.data.remove(index);
47            let updated_pair = Pair {
48                element: temp.element,
49                priority: new_priority
50            };
51            self.insert(updated_pair);
52        }
53    }
54
55    fn find_index(&self, old_value: T) -> Option<usize> {
56        for (index, pair) in self.data.iter().enumerate() {
57            if pair.element == old_value {
58                return Some(index);
59            }
60        }
61        None
62    }
63
64    pub fn top(&mut self) -> Option<Pair<T>> {
65        let last_element = self.remove_last()?;
66        if self.data.is_empty() {
67            Some(last_element)
68        } else {
69            let root_element = self.data[0].clone();
70            self.data[0] = last_element;
71            self.push_down_optimized(None);
72            Some(root_element)
73        }
74    }
75
76    fn remove_last(&mut self) -> Option<Pair<T>> {
77        if self.data.is_empty() {
78            None
79        } else {
80            self.data.pop()
81        }
82    }
83
84    // bubbles up the selected element
85    fn bubble_up(&mut self, index: Option<usize>) {
86        // as default the last element is selected
87        let mut parent_index = index.unwrap_or(self.data.len() - 1);
88        while parent_index > 0 {
89            let current_index = parent_index;
90            parent_index = self.get_parent_index(parent_index);
91            if self.data[parent_index].priority < self.data[current_index].priority {
92                self.swap(current_index, parent_index)
93            } else {
94                break;
95            }
96        }
97    }
98
99    fn bubble_up_optimized(&mut self, initial_index: Option<usize>) {
100        let mut index = initial_index.unwrap_or(self.data.len() - 1);
101        let current = self.data[index].clone();
102        while index > 0 {
103            let parent_index = self.get_parent_index(index);
104            if self.data[parent_index].priority < self.data[index].priority {
105                self.data[index] = self.data[parent_index].clone();
106                index = parent_index;
107            } else {
108                break;
109            }
110        }
111        self.data[index] = current;
112    }
113
114    fn push_down(&mut self, initial_index: Option<usize>) {
115        let index = initial_index.unwrap_or(0);
116        let mut current_index = index;
117        while current_index < self.first_leaf_index() {
118            let highest_priority_child_index = self.highest_priority_child_index(index);
119            if self.data[current_index].priority < self.data[highest_priority_child_index].priority {
120                self.swap(current_index,highest_priority_child_index);
121                current_index = highest_priority_child_index;
122            } else {
123                break;
124            }
125        }    
126    }
127
128    fn push_down_optimized(&mut self, initial_index: Option<usize>) {
129        let mut index = initial_index.unwrap_or(0);
130        let current = self.data[index].clone();
131        while index < self.first_leaf_index() {
132            let highest_priority_child_index = self.highest_priority_child_index(index);
133            if self.data[index].priority < self.data[highest_priority_child_index].priority {
134                self.data[index] = self.data[highest_priority_child_index].clone();
135                index = highest_priority_child_index;
136            } else {
137                break;
138            }
139        } 
140        self.data[index] = current;
141    }
142
143    fn first_leaf_index(&self) -> usize {
144        (self.data.len() - 2) / self.branching_factor + 1
145    }
146
147    fn get_parent_index(&self, index: usize) -> usize {
148        (index - 1) / self.branching_factor
149    }
150
151    fn swap(&mut self, first_index: usize, second_index: usize) {
152        self.data.swap(first_index, second_index);
153    }
154
155    pub fn highest_priority_child_index(&self, index: usize) -> usize {
156        // if it has no child, returns itself
157        let first_child_index = (self.branching_factor * index) + 1;
158        if self.data.len() - 1 < first_child_index {
159            return index;
160        }
161
162        let mut highest_priority_index = index;
163        for i in 1..=self.branching_factor {
164            let child_index = (self.branching_factor * index) + i;
165            if self.data.len() - 1 < child_index {
166                continue;
167            }
168
169            if self.data[child_index].priority > self.data[highest_priority_index].priority {
170                highest_priority_index = child_index;
171            }
172        }
173        highest_priority_index
174    }
175}
176
177#[derive(Debug)]
178enum DheapError {
179    EmptyHeap
180}
181
182impl std::error::Error for DheapError {}
183impl Display for DheapError {
184    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
185        match self {
186            Self::EmptyHeap => write!(f, "empty heap")
187        }
188    }
189}
190
191mod tests {
192    use super::*;
193
194    fn testing_dheap() -> DHeap<String> {
195        let mut heap = DHeap::new(None, None);
196        for i in 1..10 {
197            let example_pair = Pair {priority: i, element: i.to_string()};
198            heap.insert(example_pair);
199        }
200        heap
201    }
202
203    #[test]
204    fn get_top_test() {
205        let mut heap = testing_dheap();
206        let received = heap.top().unwrap();
207        let expected = Pair {priority: 9, element: 9.to_string()};
208
209        assert_eq!(expected.priority, received.priority);
210        assert_eq!(expected.element, received.element);
211    }
212
213    #[test]
214    fn peek_test() {
215        let heap = testing_dheap();
216        let pair = heap.peek().unwrap();
217        assert_eq!(9, pair.priority);
218    }
219
220    #[test]
221    fn update_is_correct() {
222        let mut heap = testing_dheap();
223        heap.update_priority("9".to_string(), 10);
224        let top_pair = heap.top().unwrap();
225        assert_eq!(10, top_pair.priority);
226    }
227}