v
Зеркало из https://github.com/vlang/v
1module datatypes
2
3/// Internal representation of the tree node
4@[heap]
5struct BSTreeNode[T] {
6mut:
7// Mark a node as initialized
8is_init bool
9// Value of the node
10value T
11// The parent of the node
12parent &BSTreeNode[T] = unsafe { 0 }
13// The left side with value less than the
14// value of this node
15left &BSTreeNode[T] = unsafe { 0 }
16// The right side with value grater than the
17// value of thiss node
18right &BSTreeNode[T] = unsafe { 0 }
19}
20
21// Create new root bst node
22fn new_root_node[T](value T) &BSTreeNode[T] {
23return &BSTreeNode[T]{
24is_init: true
25value: value
26parent: new_none_node[T](true)
27left: new_none_node[T](false)
28right: new_none_node[T](false)
29}
30}
31
32// new_node creates a new bst node with a parent reference.
33fn new_node[T](parent &BSTreeNode[T], value T) &BSTreeNode[T] {
34return &BSTreeNode[T]{
35is_init: true
36value: value
37parent: parent
38}
39}
40
41// new_none_node creates a dummy node.
42fn new_none_node[T](init bool) &BSTreeNode[T] {
43return &BSTreeNode[T]{
44is_init: init
45}
46}
47
48// bind to an actual instance of a node.
49fn (mut node BSTreeNode[T]) bind(mut to_bind BSTreeNode[T], left bool) {
50node.left = to_bind.left
51node.right = to_bind.right
52node.value = to_bind.value
53node.is_init = to_bind.is_init
54to_bind = new_none_node[T](false)
55}
56
57// Pure Binary Seach Tree implementation
58//
59// Pure V implementation of the Binary Search Tree
60// Time complexity of main operation O(log N)
61// Space complexity O(N)
62pub struct BSTree[T] {
63mut:
64root &BSTreeNode[T] = unsafe { 0 }
65}
66
67// insert give the possibility to insert an element in the BST.
68pub fn (mut bst BSTree[T]) insert(value T) bool {
69if bst.is_empty() {
70bst.root = new_root_node(value)
71return true
72}
73return bst.insert_helper(mut bst.root, value)
74}
75
76// insert_helper walks the tree and inserts the given node.
77fn (mut bst BSTree[T]) insert_helper(mut node BSTreeNode[T], value T) bool {
78if node.value < value {
79if unsafe { node.right != 0 } && node.right.is_init {
80return bst.insert_helper(mut node.right, value)
81}
82node.right = new_node(node, value)
83return true
84} else if node.value > value {
85if unsafe { node.left != 0 } && node.left.is_init {
86return bst.insert_helper(mut node.left, value)
87}
88node.left = new_node(node, value)
89return true
90}
91return false
92}
93
94// contains checks if an element with a given `value` is inside the BST.
95pub fn (bst &BSTree[T]) contains(value T) bool {
96return bst.contains_helper(bst.root, value)
97}
98
99// contains_helper is a helper function to walk the tree, and return
100// the absence or presence of the `value`.
101fn (bst &BSTree[T]) contains_helper(node &BSTreeNode[T], value T) bool {
102if unsafe { node == 0 } || !node.is_init {
103return false
104}
105if node.value < value {
106return bst.contains_helper(node.right, value)
107} else if node.value > value {
108return bst.contains_helper(node.left, value)
109}
110assert node.value == value
111return true
112}
113
114// remove removes an element with `value` from the BST.
115pub fn (mut bst BSTree[T]) remove(value T) bool {
116if bst.is_empty() {
117return false
118}
119return bst.remove_helper(mut bst.root, value, false)
120}
121
122fn (mut bst BSTree[T]) remove_helper(mut node BSTreeNode[T], value T, left bool) bool {
123if !node.is_init {
124return false
125}
126if node.value == value {
127if unsafe { node.left != 0 } && node.left.is_init {
128// In order to remove the element we need to bring up as parent the max of the
129// left sub-tree.
130mut max_node := bst.get_max_from_right(node.left)
131node.bind(mut max_node, true)
132} else if unsafe { node.right != 0 } && node.right.is_init {
133// Bring up the element with the minimum value in the right sub-tree.
134mut min_node := bst.get_min_from_left(node.right)
135node.bind(mut min_node, false)
136} else {
137mut parent := node.parent
138if left {
139parent.left = new_none_node[T](false)
140} else {
141parent.right = new_none_node[T](false)
142}
143node = new_none_node[T](false)
144}
145return true
146}
147
148if node.value < value {
149return bst.remove_helper(mut node.right, value, false)
150}
151return bst.remove_helper(mut node.left, value, true)
152}
153
154// get_max_from_right returns the max element of the BST following the right branch.
155fn (bst &BSTree[T]) get_max_from_right(node &BSTreeNode[T]) &BSTreeNode[T] {
156if unsafe { node == 0 } {
157return new_none_node[T](false)
158}
159right_node := node.right
160if unsafe { right_node == 0 } || !right_node.is_init {
161return node
162}
163return bst.get_max_from_right(right_node)
164}
165
166// get_min_from_left returns the min element of the BST by following the left branch.
167fn (bst &BSTree[T]) get_min_from_left(node &BSTreeNode[T]) &BSTreeNode[T] {
168if unsafe { node == 0 } {
169return new_none_node[T](false)
170}
171left_node := node.left
172if unsafe { left_node == 0 } || !left_node.is_init {
173return node
174}
175return bst.get_min_from_left(left_node)
176}
177
178// is_empty checks if the BST is empty
179pub fn (bst &BSTree[T]) is_empty() bool {
180return unsafe { bst.root == 0 }
181}
182
183// in_order_traversal traverses the BST in order, and returns the result as an array.
184pub fn (bst &BSTree[T]) in_order_traversal() []T {
185mut result := []T{}
186bst.in_order_traversal_helper(bst.root, mut result)
187return result
188}
189
190// in_order_traversal_helper helps traverse the BST, and accumulates the result in the `result` array.
191fn (bst &BSTree[T]) in_order_traversal_helper(node &BSTreeNode[T], mut result []T) {
192if unsafe { node == 0 } || !node.is_init {
193return
194}
195bst.in_order_traversal_helper(node.left, mut result)
196result << node.value
197bst.in_order_traversal_helper(node.right, mut result)
198}
199
200// post_order_traversal traverses the BST in post order, and returns the result in an array.
201pub fn (bst &BSTree[T]) post_order_traversal() []T {
202mut result := []T{}
203bst.post_order_traversal_helper(bst.root, mut result)
204return result
205}
206
207// post_order_traversal_helper is a helper function that traverses the BST in post order,
208// accumulating the result in an array.
209fn (bst &BSTree[T]) post_order_traversal_helper(node &BSTreeNode[T], mut result []T) {
210if unsafe { node == 0 } || !node.is_init {
211return
212}
213
214bst.post_order_traversal_helper(node.left, mut result)
215bst.post_order_traversal_helper(node.right, mut result)
216result << node.value
217}
218
219// pre_order_traversal traverses the BST in pre order, and returns the result as an array.
220pub fn (bst &BSTree[T]) pre_order_traversal() []T {
221mut result := []T{}
222bst.pre_order_traversal_helper(bst.root, mut result)
223return result
224}
225
226// pre_order_traversal_helper is a helper function to traverse the BST
227// in pre order and accumulates the results in an array.
228fn (bst &BSTree[T]) pre_order_traversal_helper(node &BSTreeNode[T], mut result []T) {
229if unsafe { node == 0 } || !node.is_init {
230return
231}
232result << node.value
233bst.pre_order_traversal_helper(node.left, mut result)
234bst.pre_order_traversal_helper(node.right, mut result)
235}
236
237// get_node is a helper method to ge the internal representation of the node with the `value`.
238fn (bst &BSTree[T]) get_node(node &BSTreeNode[T], value T) &BSTreeNode[T] {
239if unsafe { node == 0 } || !node.is_init {
240return new_none_node[T](false)
241}
242if node.value == value {
243return node
244}
245
246if node.value < value {
247return bst.get_node(node.right, value)
248}
249return bst.get_node(node.left, value)
250}
251
252// to_left returns the value of the node to the left of the node with `value` specified if it exists,
253// otherwise the a false value is returned.
254//
255// An example of usage can be the following one
256//```v
257// left_value, exist := bst.to_left(10)
258//```
259pub fn (bst &BSTree[T]) to_left(value T) !T {
260if bst.is_empty() {
261return error('BSTree is empty')
262}
263node := bst.get_node(bst.root, value)
264if !node.is_init {
265return error('BSTree is not initialized')
266}
267left_node := node.left
268return left_node.value
269}
270
271// to_right return the value of the element to the right of the node with `value` specified, if exist
272// otherwise, the boolean value is false
273// An example of usage can be the following one
274//
275//```v
276// left_value, exist := bst.to_right(10)
277//```
278pub fn (bst &BSTree[T]) to_right(value T) !T {
279if bst.is_empty() {
280return error('BSTree is empty')
281}
282node := bst.get_node(bst.root, value)
283if !node.is_init {
284return error('BSTree is not initialized')
285}
286right_node := node.right
287return right_node.value
288}
289
290// max return the max element inside the BST.
291// Time complexity O(N) if the BST is not balanced
292pub fn (bst &BSTree[T]) max() !T {
293if bst.is_empty() {
294return error('BSTree is empty')
295}
296max := bst.get_max_from_right(bst.root)
297if !max.is_init {
298return error('BSTree is not initialized')
299}
300return max.value
301}
302
303// min return the minimum element in the BST.
304// Time complexity O(N) if the BST is not balanced.
305pub fn (bst &BSTree[T]) min() !T {
306if bst.is_empty() {
307return error('BSTree is empty')
308}
309min := bst.get_min_from_left(bst.root)
310if !min.is_init {
311return error('BSTree is not initialized')
312}
313return min.value
314}
315