binary_tree/
test.rs

1//! Data structures and algorithms for testing purposes.
2
3use std::mem;
4use std::cmp;
5
6use Node;
7use NodeMut;
8
9#[derive(Clone, Copy, Debug, PartialEq, Eq)]
10pub enum Level {
11    Balanced(u32),
12    Imbalanced(u32),
13}
14
15impl Level {
16    pub fn is_balanced(self) -> bool {
17        if let Level::Balanced(_) = self {
18            true
19        } else {
20            false
21        }
22    }
23
24    pub fn as_u32(self) -> u32 {
25        match self {
26            Level::Balanced(e) |
27            Level::Imbalanced(e) => e,
28        }
29    }
30}
31
32/// Recursively calculate the level of this node and check whether it is
33/// balanced.
34///
35/// `level = height + 1`. Recursive, hence risk of stack blow up depending on
36/// the height of the tree! The node is considered balanced if, at every node,
37/// the difference in levels of the child nodes is not greater than `tolerance`.
38pub fn compute_level<N: Node>(node: &N, tolerance: u32) -> Level {
39    use test::Level::*;
40
41    let llevel = node.left().map_or(Balanced(0), |n| compute_level(n, tolerance));
42    let rlevel = node.right().map_or(Balanced(0), |n| compute_level(n, tolerance));
43
44    if llevel.is_balanced() && rlevel.is_balanced() {
45        let max = cmp::max(llevel.as_u32(), rlevel.as_u32());
46        let min = cmp::min(llevel.as_u32(), rlevel.as_u32());
47        if max - min > tolerance {
48            Imbalanced(max + 1)
49        } else {
50            Balanced(max + 1)
51        }
52    } else {
53        Imbalanced(cmp::max(llevel.as_u32(), rlevel.as_u32()) + 1)
54    }
55}
56
57#[derive(Debug)]
58/// A minimal `Node` implementation.
59///
60/// ## When should you use `TestNode`?
61///
62/// You should not use `TestNode` for anything, except may be to get to know what
63/// a binary tree is!
64pub struct TestNode<T> {
65    pub val: T,
66    pub left: Option<Box<TestNode<T>>>,
67    pub right: Option<Box<TestNode<T>>>,
68}
69
70impl<T> TestNode<T> {
71    pub fn new(val: T) -> TestNode<T> {
72        TestNode {
73            val: val,
74            left: None,
75            right: None,
76        }
77    }
78}
79
80impl<T> Node for TestNode<T> {
81    type Value = T;
82
83    fn left(&self) -> Option<&Self> {
84        self.left.as_ref().map(|st| &**st)
85    }
86
87    fn right(&self) -> Option<&Self> {
88        self.right.as_ref().map(|st| &**st)
89    }
90
91    fn value(&self) -> &T {
92        &self.val
93    }
94}
95
96impl<T> NodeMut for TestNode<T> {
97    type NodePtr = Box<TestNode<T>>;
98
99    fn detach_left(&mut self) -> Option<Self::NodePtr> {
100        self.left.take()
101    }
102
103    fn detach_right(&mut self) -> Option<Self::NodePtr> {
104        self.right.take()
105    }
106
107    fn insert_left(&mut self, mut st: Option<Self::NodePtr>) -> Option<Self::NodePtr> {
108        mem::swap(&mut self.left, &mut st);
109        st
110    }
111
112    fn insert_right(&mut self, mut st: Option<Self::NodePtr>) -> Option<Self::NodePtr> {
113        mem::swap(&mut self.right, &mut st);
114        st
115    }
116
117    fn value_mut(&mut self) -> &mut T {
118        &mut self.val
119    }
120
121    fn into_parts(self) -> (T, Option<Self::NodePtr>, Option<Self::NodePtr>) {
122        (self.val, self.left, self.right)
123    }
124
125    fn left_mut(&mut self) -> Option<&mut Self> {
126        self.left.as_mut().map(|l| &mut **l)
127    }
128
129    fn right_mut(&mut self) -> Option<&mut Self> {
130        self.right.as_mut().map(|r| &mut **r)
131    }
132}
133
134#[cfg(test)]
135mod tests {
136    use super::TestNode;
137    use Node;
138    use NodeMut;
139
140    fn new_node<T>(val: T) -> Box<TestNode<T>> {
141        Box::new(TestNode::new(val))
142    }
143
144    fn test_tree() -> TestNode<u32> {
145        TestNode {
146            val: 20,
147            left: Some(new_node(10)),
148            right: Some(Box::new(TestNode {
149                val: 30,
150                left: Some(new_node(25)),
151                right: None,
152            })),
153        }
154    }
155
156    #[test]
157    fn rotate() {
158        let mut tt = test_tree();
159
160        tt.rotate_left().unwrap();
161        assert_eq!(*tt.value(),                    30);
162        assert_eq!(tt.left.as_ref().unwrap().val,  20);
163        assert_eq!(tt.left.as_ref().unwrap()
164                     .left.as_ref().unwrap().val,  10);
165        assert_eq!(tt.left.as_ref().unwrap()
166                     .right.as_ref().unwrap().val, 25);
167
168        tt.rotate_right().unwrap();
169        assert_eq!(*tt.value(),                    20);
170        assert_eq!(tt.left.as_ref().unwrap().val,  10);
171        assert_eq!(tt.right.as_ref().unwrap().val, 30);
172        assert_eq!(tt.right.as_ref().unwrap()
173                     .left.as_ref().unwrap().val,  25);
174    }
175
176    #[test]
177    fn walk() {
178        use WalkAction::*;
179
180        let mut tt = test_tree();
181        let mut steps = vec![Right, Left, Stop];
182        {
183            let mut step_iter = steps.drain(..);
184            tt.walk_reshape(|_| step_iter.next().unwrap(),
185                            |st| assert_eq!(st.val, 25),
186                            |st, action| {
187                                match action {
188                                    Right => assert_eq!(st.val, 20),
189                                    Left => assert_eq!(st.val, 30),
190                                    Stop => unreachable!(),
191                                }
192                            });
193        }
194        assert_eq!(steps.len(), 0);
195    }
196
197    #[test]
198    fn remove() {
199        let mut tt = test_tree();
200        let tn = tt.right.as_mut().unwrap().try_remove(|_, _| ());
201        assert_eq!(tn.unwrap().value(), &30);
202        assert_eq!(tt.right.as_ref().unwrap().value(), &25);
203        let mut tt2 = test_tree();
204        {
205            let right = tt2.right.as_mut().unwrap();
206            right.right = Some(new_node(40));
207        }
208        let tn = tt2.right.as_mut().unwrap().try_remove(|_, _| ());
209        assert_eq!(tn.unwrap().value(), &30);
210        assert_eq!(tt.right.as_ref().unwrap().value(), &25);
211    }
212
213    #[test]
214    fn stack_blow() {
215        use iter::IntoIter;
216        let mut pt = new_node(20);
217        for _ in 0..200000 {
218            let mut pt2 = new_node(20);
219            pt2.insert_left(Some(pt));
220            pt = pt2;
221        }
222        // comment out the line below to observe a stack overflow
223        let _: IntoIter<TestNode<_>> = IntoIter::new(Some(pt));
224    }
225}