Skip to content

Commit 26c5bb8

Browse files
rust: Binary Heap
1 parent b8a3ec7 commit 26c5bb8

File tree

1 file changed

+179
-0
lines changed
  • golang/data_structures/binary_heap_nov_6_2024

1 file changed

+179
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
#[derive(Debug)]
2+
struct Heap<T> {
3+
nodes: Vec<Option<T>>,
4+
}
5+
6+
impl<T: std::fmt::Debug + std::cmp::PartialOrd> Heap<T> {
7+
fn new() -> Self {
8+
Self { nodes: Vec::new() }
9+
}
10+
11+
fn push(&mut self, v: T) {
12+
let mut new_node_index = self.nodes.len();
13+
14+
self.nodes.push(Some(v));
15+
16+
let mut parent_index = parent(new_node_index);
17+
18+
while let Some(index) = parent_index {
19+
if self.nodes[new_node_index] <= self.nodes[index] {
20+
break;
21+
}
22+
23+
let tmp = self.nodes[index].take();
24+
self.nodes[index] = self.nodes[new_node_index].take();
25+
self.nodes[new_node_index] = tmp;
26+
parent_index = parent(index);
27+
new_node_index = index;
28+
}
29+
}
30+
31+
fn pop(&mut self) -> Option<T> {
32+
if self.nodes.is_empty() {
33+
return None;
34+
}
35+
36+
let nodes_len = self.nodes.len();
37+
38+
let value = self.nodes[0].take();
39+
// TODO: reduce vec size.
40+
self.nodes[0] = self.nodes[nodes_len - 1].take();
41+
42+
let mut current_index = 0;
43+
loop {
44+
let left = left_child(current_index);
45+
let right = right_child(current_index);
46+
47+
if self.nodes.get(left) >= self.nodes.get(right)
48+
&& self.nodes.get(left).is_some()
49+
&& self
50+
.nodes
51+
.get(left)
52+
.map(|v| v > &self.nodes[current_index])
53+
.unwrap_or(false)
54+
{
55+
let tmp = self.nodes[current_index].take();
56+
self.nodes[current_index] = self.nodes[left].take();
57+
self.nodes[left] = tmp;
58+
current_index = left;
59+
} else if self.nodes.get(right).is_some()
60+
&& self
61+
.nodes
62+
.get(right)
63+
.map(|v| v > &self.nodes[current_index])
64+
.unwrap_or(false)
65+
{
66+
let tmp = self.nodes[current_index].take();
67+
self.nodes[current_index] = self.nodes[right].take();
68+
self.nodes[right] = tmp;
69+
current_index = right
70+
} else {
71+
break;
72+
}
73+
}
74+
75+
self.nodes.truncate(nodes_len - 1);
76+
77+
value
78+
}
79+
}
80+
81+
fn parent(i: usize) -> Option<usize> {
82+
if i == 0 {
83+
None
84+
} else {
85+
Some((i - 1) / 2)
86+
}
87+
}
88+
89+
fn left_child(i: usize) -> usize {
90+
2 * i + 1
91+
}
92+
93+
fn right_child(i: usize) -> usize {
94+
2 * i + 2
95+
}
96+
97+
fn main() {
98+
let mut heap = Heap::new();
99+
heap.push(1);
100+
heap.push(2);
101+
heap.push(3);
102+
heap.push(5);
103+
heap.push(4);
104+
dbg!(&heap);
105+
106+
dbg!(heap.pop());
107+
dbg!(heap.pop());
108+
dbg!(heap.pop());
109+
dbg!(heap.pop());
110+
dbg!(heap.pop());
111+
dbg!(heap.pop());
112+
}
113+
114+
#[cfg(test)]
115+
mod tests {
116+
use std::collections::BinaryHeap;
117+
118+
use super::*;
119+
use quickcheck::quickcheck;
120+
121+
#[derive(Debug, Clone)]
122+
enum Action {
123+
Push(i32),
124+
Pop,
125+
}
126+
127+
impl quickcheck::Arbitrary for Action {
128+
fn arbitrary(g: &mut quickcheck::Gen) -> Self {
129+
if bool::arbitrary(g) {
130+
Action::Push(i32::arbitrary(g))
131+
} else {
132+
Action::Pop
133+
}
134+
}
135+
}
136+
137+
quickcheck! {
138+
#[test]
139+
fn test_heap(xs: Vec<i32>) -> bool{
140+
let mut heap = Heap::new();
141+
let mut model = BinaryHeap::new();
142+
143+
for x in xs.iter() {
144+
heap.push(x);
145+
model.push(x);
146+
}
147+
148+
for _ in 0..xs.len() {
149+
assert_eq!(model.pop(), heap.pop());
150+
}
151+
152+
true
153+
}
154+
155+
#[test]
156+
fn test_heap_2(actions: Vec<Action>) -> bool {
157+
let mut heap = Heap::new();
158+
let mut model = BinaryHeap::new();
159+
160+
for action in actions {
161+
match action {
162+
Action::Push(v) => {
163+
model.push(v);
164+
heap.push(v);
165+
},
166+
Action::Pop => {
167+
assert_eq!(model.pop(), heap.pop());
168+
}
169+
}
170+
}
171+
172+
while !model.is_empty() {
173+
assert_eq!(model.pop(), heap.pop());
174+
}
175+
176+
true
177+
}
178+
}
179+
}

0 commit comments

Comments
 (0)