flex_algo/binary_search_tree.rs
1use std::fmt::Debug;
2
3/// BinarySearchTree
4///
5/// This crate implements a Binary Search Tree data structure with insert,
6/// preorder traversal, search and validate algorithms.
7///
8#[derive(Debug)]
9pub struct BST<T>(Option<Box<BinaryNode<T>>>);
10
11#[derive(Debug)]
12pub struct BinaryNode<T> {
13 data: T,
14 left: BST<T>,
15 right: BST<T>,
16}
17
18impl<T> BinaryNode<T> {
19 pub fn new(data: T) -> Self {
20 BinaryNode {
21 data,
22 left: BST(None),
23 right: BST(None),
24 }
25 }
26}
27
28impl<T> BST<T> {
29 /// Create a new BinarySearchTree
30 ///
31 /// # Example
32 ///
33 /// ```
34 /// use flex_algo::BST;
35 ///
36 /// let mut bst = BST::new();
37 /// bst.insert(3);
38 /// bst.insert(2);
39 /// bst.insert(1);
40 ///
41 /// ```
42 ///
43 pub fn new() -> Self {
44 BST(None)
45 }
46}
47
48impl<T> BST<T>
49where T: PartialOrd + Copy
50{
51 /// Insert into a new BinarySearchTree
52 ///
53 /// # Example
54 ///
55 /// ```
56 /// use flex_algo::BST;
57 ///
58 /// let mut bst = BST::new();
59 /// bst.insert(3);
60 /// bst.insert(2);
61 /// bst.insert(1);
62 ///
63 /// ```
64 ///
65 pub fn insert(&mut self, data: T) -> bool {
66 match self.0 {
67 Some(ref mut node) => {
68 if node.data == data {
69 return false;
70 }
71 if data < node.data {
72 return node.left.insert(data);
73 } else {
74 return node.right.insert(data);
75 }
76 }
77 None => {
78 self.0 = Some(Box::new(BinaryNode::new(data)));
79 }
80 }
81 true
82 }
83
84 /// Validate a new BinarySearchTree
85 ///
86 /// # Example
87 ///
88 /// ```
89 /// use flex_algo::BST;
90 ///
91 /// let mut bst = BST::new();
92 /// bst.insert(3);
93 /// bst.insert(2);
94 /// bst.insert(1);
95 ///
96 /// let is_valid = bst.is_valid(i32::MIN, i32::MAX);
97 /// assert_eq!(is_valid, true);
98 ///
99 /// ```
100 ///
101 pub fn is_valid(&self, min: T, max: T) -> bool {
102 if let Some(ref node) = self.0 {
103 if node.data <= min || node.data >= max {
104 return false;
105 }
106 if !node.left.is_valid(min, node.data) {
107 return false;
108 }
109 if !node.right.is_valid(min, max) {
110 return false;
111 }
112 }
113 true
114 }
115
116 /// Search a new BinarySearchTree
117 ///
118 /// # Example
119 ///
120 /// ```
121 /// use flex_algo::BST;
122 ///
123 /// let mut bst = BST::new();
124 /// bst.insert(3);
125 /// bst.insert(2);
126 /// bst.insert(1);
127 ///
128 /// let none = bst.search(5);
129 /// assert_eq!(none, None);
130 ///
131 /// let found = bst.search(2);
132 /// assert_eq!(found, Some(2));
133 ///
134 /// ```
135 ///
136 pub fn search(&self, data: T) -> Option<T> {
137 if let Some(ref node) = self.0 {
138 if node.data == data {
139 return Some(data);
140 }
141 if data < node.data {
142 return node.left.search(data);
143 } else {
144 return node.right.search(data);
145 }
146 }
147 None
148 }
149}
150
151impl<T: Debug> BST<T> {
152 /// Traversal a new BinarySearchTree preorder
153 ///
154 /// # Example
155 ///
156 /// ```
157 /// use flex_algo::BST;
158 ///
159 /// let mut bst = BST::new();
160 /// bst.insert(3);
161 /// bst.insert(2);
162 /// bst.insert(1);
163 ///
164 /// bst.print_preorder(0);
165 ///
166 /// ```
167 ///
168 pub fn print_preorder(&self, depth: i32) {
169 if let Some(ref node) = self.0 {
170 node.left.print_preorder(depth + 1);
171 let mut space = String::new();
172 for _ in 0..depth {
173 space.push('.');
174 }
175 println!("{}{:?}", space, node.data);
176 node.right.print_preorder(depth + 1);
177 }
178 }
179}
180
181#[cfg(test)]
182mod tests {
183 use super::*;
184
185 #[test]
186 fn test_bst_insert() {
187 let mut bst = BST::new();
188 bst.insert(3);
189 bst.insert(2);
190 bst.insert(1);
191 bst.print_preorder(0);
192 }
193
194 #[test]
195 fn test_bst_is_valid() {
196 let mut bst = BST::new();
197 bst.insert(3);
198 bst.insert(2);
199 bst.insert(1);
200
201 let is_valid = bst.is_valid(i32::MIN, i32::MAX);
202 assert_eq!(is_valid, true);
203 }
204
205 #[test]
206 fn test_bst_search() {
207 let mut bst = BST::new();
208 bst.insert(3);
209 bst.insert(2);
210 bst.insert(1);
211 let none = bst.search(5);
212 assert_eq!(none, None);
213
214 let found = bst.search(2);
215 assert_eq!(found, Some(2));
216 }
217}