Skip to content

Commit 4adbba4

Browse files
author
user
committed
Epoch
1 parent 7ae19c2 commit 4adbba4

File tree

2 files changed

+110
-93
lines changed

2 files changed

+110
-93
lines changed

readme.md

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,11 @@ When implementing an AVL tree, there are some choices:
66
* Storing the balance factor or height in a node.
77
* Taking a recursive or iterative approach.
88

9-
This is a recursive implementation of an AVL tree that stores the height in a node and does not store the parent pointer in it. Key points:
9+
This is an iterative implementation of an AVL tree that stores the height in a node and does not store the parent pointer in it. Key points:
1010
* Written in pure Rust.
11-
* No unsafe code (other than [the mutable iterator](src/avl.rs#L544)).
1211
* The key data type can be any type that has Ord.
1312
* Each node is identified by a key, and so there are no nodes with the same key.
1413

15-
[The iterative implementation](/../iterative)
16-
is slightly faster, but uses more unsafe code and is more complex because it requires tracing the path of ancestor nodes during tree modification.
17-
1814
## Description
1915
<picture>
2016
<source media="(prefers-color-scheme: dark)" srcset="img/AVLTreeDarkTheme.png">

src/avl.rs

Lines changed: 109 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -78,16 +78,16 @@ impl<K: Ord, V> AvlTree<K, V> {
7878

7979

8080
pub fn pop_first(&mut self) -> Option<(K, V)> {
81-
let (key, value) = self.root.remove_minimum()?;
81+
let min: Node<K, V> = self.root.remove_minimum()?;
8282
self.node_count -= 1;
83-
Some((key, value))
83+
Some((min.key, min.value))
8484
}
8585

8686

8787
pub fn pop_last(&mut self) -> Option<(K, V)> {
88-
let (key, value) = self.root.remove_maximum()?;
88+
let max: Node<K, V> = self.root.remove_maximum()?;
8989
self.node_count -= 1;
90-
Some((key, value))
90+
Some((max.key, max.value))
9191
}
9292

9393

@@ -121,23 +121,84 @@ impl<K: Ord, V> AvlTree<K, V> {
121121

122122

123123
pub fn insert(&mut self, key: K, value: V) -> Option<V> {
124-
match self.root.insert_(Box::new(Node::new(key, value))) {
125-
None => {
126-
self.node_count += 1;
127-
None
124+
let mut path: Vec<*mut Node<K, V>> = Vec::with_capacity(128);
125+
let mut current: Option<&mut Node<K, V>> = self.root.as_deref_mut();
126+
while let Some(node) = current {
127+
path.push(node);
128+
if key < node.key {
129+
current = node.left.as_deref_mut();
130+
} else if key > node.key {
131+
current = node.right.as_deref_mut();
132+
} else {
133+
return Some(memory::replace(&mut node.value, value));
134+
}
135+
}
136+
let new: Box<Node<K, V>> = Box::new(Node::new(key, value));
137+
if let Some(parent) = path.last() {
138+
let parent: &mut Node<K, V> = unsafe { &mut **parent };
139+
if new.key < parent.key {
140+
parent.left = Some(new);
141+
} else {
142+
parent.right = Some(new);
128143
}
129-
Some(old) => Some(old),
144+
} else {
145+
self.root = Some(new);
130146
}
147+
AvlTree::retrace(path, false);
148+
self.node_count += 1;
149+
None
131150
}
132151

133152

134153
pub fn remove(&mut self, key: &K) -> Option<V> {
135-
match self.root.remove(key) {
136-
Some(removed) => {
137-
self.node_count -= 1;
138-
Some(removed)
154+
let mut path: Vec<*mut Node<K, V>> = Vec::with_capacity(128);
155+
let mut current: Option<&mut Node<K, V>> = self.root.as_deref_mut();
156+
while let Some(node) = current {
157+
if *key < node.key {
158+
path.push(node);
159+
current = node.left.as_deref_mut();
160+
} else if *key > node.key {
161+
path.push(node);
162+
current = node.right.as_deref_mut();
163+
} else {
164+
current = Some(node);
165+
break;
166+
}
167+
}
168+
let node: &mut Node<K, V> = current?;
169+
let removed: V;
170+
if node.left.is_some() && node.right.is_some() {
171+
let successor: Node<K, V> = node.right.remove_minimum().unwrap();
172+
let _ = memory::replace(&mut node.key, successor.key);
173+
removed = memory::replace(&mut node.value, successor.value);
174+
path.push(node);
175+
} else if let Some(mut child) = node.left.take().or(node.right.take()) {
176+
memory::swap(node, &mut child); // `node` is `child` now.
177+
removed = child.value;
178+
} else if let Some(parent) = path.last() {
179+
let parent: &mut Node<K, V> = unsafe { &mut **parent };
180+
removed = if *key < parent.key {
181+
parent.left.take()
182+
} else {
183+
parent.right.take()
184+
}.unwrap().value;
185+
} else {
186+
removed = self.root.take().unwrap().value;
187+
}
188+
AvlTree::retrace(path, true);
189+
self.node_count -= 1;
190+
Some(removed)
191+
}
192+
193+
194+
fn retrace(mut path: Vec<*mut Node<K, V>>, for_removal: bool) {
195+
while let Some(ancestor) = path.pop() {
196+
let ancestor: &mut Node<K, V> = unsafe { &mut *ancestor };
197+
ancestor.update_height();
198+
ancestor.rebalance();
199+
if ancestor.balance_factor().abs() == for_removal as i32 {
200+
break;
139201
}
140-
None => None,
141202
}
142203
}
143204

@@ -306,7 +367,6 @@ impl<K: Ord, V> Node<K, V> {
306367

307368
// Rebalances a subtree rooted at `self`.
308369
fn rebalance(&mut self) {
309-
self.update_height();
310370
if self.balance_factor() == -2 { // `self` is left-heavy.
311371
let left: &mut Node<K, V> = self.left.as_deref_mut().unwrap();
312372
if left.balance_factor() == 1 {
@@ -327,10 +387,8 @@ impl<K: Ord, V> Node<K, V> {
327387

328388
trait OptionNodeExt<K: Ord, V> {
329389
fn height(&self) -> u8;
330-
fn insert_(&mut self, new: Box<Node<K, V>>) -> Option<V>;
331-
fn remove(&mut self, key: &K) -> Option<V>;
332-
fn remove_minimum(&mut self) -> Option<(K, V)>;
333-
fn remove_maximum(&mut self) -> Option<(K, V)>;
390+
fn remove_minimum(&mut self) -> Option<Node<K, V>>;
391+
fn remove_maximum(&mut self) -> Option<Node<K, V>>;
334392
}
335393

336394

@@ -341,84 +399,47 @@ impl<K: Ord, V> OptionNodeExt<K, V> for Option<Box<Node<K, V>>> {
341399
}
342400

343401

344-
fn insert_(&mut self, new: Box<Node<K, V>>) -> Option<V> {
345-
let Some(mut node) = self.take() else {
346-
*self = Some(new);
347-
return None;
348-
};
349-
let old: Option<V>;
350-
if new.key < node.key {
351-
old = node.left.insert_(new);
352-
} else if new.key > node.key {
353-
old = node.right.insert_(new);
354-
} else {
355-
old = Some(memory::replace(&mut node.value, new.value));
402+
fn remove_minimum(&mut self) -> Option<Node<K, V>> {
403+
let mut path: Vec<*mut Node<K, V>> = Vec::with_capacity(128);
404+
let mut current: Option<&mut Node<K, V>> = self.as_deref_mut();
405+
while let Some(node) = current {
406+
path.push(node);
407+
current = node.left.as_deref_mut();
356408
}
357-
node.rebalance();
358-
*self = Some(node);
359-
old
360-
}
361-
362-
363-
fn remove(&mut self, key: &K) -> Option<V> {
364-
let Some(mut node) = self.take() else {
365-
return None;
366-
};
367-
let removed: Option<V>;
368-
if *key < node.key {
369-
removed = node.left.remove(key);
370-
} else if *key > node.key {
371-
removed = node.right.remove(key);
372-
} else if node.left.is_some() && node.right.is_some() {
373-
removed = Some(node.value);
374-
(node.key, node.value) = node.right.remove_minimum().unwrap();
375-
} else if let Some(child) = node.left.or(node.right) {
376-
removed = Some(node.value);
377-
node = child;
409+
let node: &mut Node<K, V> = unsafe { &mut *path.pop()? };
410+
let min: Box<Node<K, V>>;
411+
if let Some(mut right) = node.right.take() {
412+
memory::swap(node, &mut right); // `node` is `right` now.
413+
min = right;
414+
} else if let Some(parent) = path.last() {
415+
min = unsafe { &mut **parent }.left.take().unwrap();
378416
} else {
379-
return Some(node.value);
417+
min = self.take().unwrap();
380418
}
381-
node.rebalance();
382-
*self = Some(node);
383-
removed
419+
AvlTree::retrace(path, true);
420+
Some(*min)
384421
}
385422

386423

387-
fn remove_minimum(&mut self) -> Option<(K, V)> {
388-
let Some(mut node) = self.take() else {
389-
return None
390-
};
391-
let min: Option<(K, V)>;
392-
if node.left.is_some() {
393-
min = node.left.remove_minimum();
394-
} else if let Some(right) = node.right {
395-
min = Some((node.key, node.value));
396-
node = right;
397-
} else {
398-
return Some((node.key, node.value));
424+
fn remove_maximum(&mut self) -> Option<Node<K, V>> {
425+
let mut path: Vec<*mut Node<K, V>> = Vec::with_capacity(128);
426+
let mut current: Option<&mut Node<K, V>> = self.as_deref_mut();
427+
while let Some(node) = current {
428+
path.push(node);
429+
current = node.right.as_deref_mut();
399430
}
400-
node.rebalance();
401-
*self = Some(node);
402-
min
403-
}
404-
405-
406-
fn remove_maximum(&mut self) -> Option<(K, V)> {
407-
let Some(mut node) = self.take() else {
408-
return None
409-
};
410-
let max: Option<(K, V)>;
411-
if node.right.is_some() {
412-
max = node.right.remove_maximum();
413-
} else if let Some(left) = node.left {
414-
max = Some((node.key, node.value));
415-
node = left;
431+
let node: &mut Node<K, V> = unsafe { &mut *path.pop()? };
432+
let max: Box<Node<K, V>>;
433+
if let Some(mut left) = node.left.take() {
434+
memory::swap(node, &mut left); // `node` is `left` now.
435+
max = left;
436+
} else if let Some(parent) = path.last() {
437+
max = unsafe { &mut **parent }.right.take().unwrap();
416438
} else {
417-
return Some((node.key, node.value));
439+
max = self.take().unwrap();
418440
}
419-
node.rebalance();
420-
*self = Some(node);
421-
max
441+
AvlTree::retrace(path, true);
442+
Some(*max)
422443
}
423444

424445
}

0 commit comments

Comments
 (0)