-
Notifications
You must be signed in to change notification settings - Fork 0
/
binary_tree_search.rb
326 lines (251 loc) · 7.41 KB
/
binary_tree_search.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
require "pry"
module Comparable
#Dont know what to do here.... yet
end
class Node
attr_accessor :left_c, :right_c, :data
def initialize(data=nil)
@data = data
@left_c =nil
@right_c =nil
end
end
class Tree
attr_accessor :root
def initialize (arr)
@arr = arr
@root = build_tree(arr)
end
def build_tree(arr)
arr.uniq!
pp arr
#TO INDUCE TO BALANCE PUT root = Node.new(arr[arr.length/2])
root = Node.new(arr.first)
arr.each do |d|
d.to_i
bilding(root, d)
end
return root
end
#if DATA is Greater than... goes Rigth
#if DATA is lower than... goes Left
#if DATA is equal than... no, that never would happen in this code
def bilding(node, d)
if d > node.data
if node.right_c
bilding(node.right_c, d)
else
node.right_c = Node.new(d)
end
elsif d < node.data
if node.left_c
bilding(node.left_c, d)
else
node.left_c = Node.new(d)
end
end
end
def insert(value)
node = @root
def get (node, value)
if value > node.data
if node.right_c
get(node.right_c, value)
else
node.right_c = Node.new(value)
end
elsif value < node.data
if node.left_c
get(node.left_c, value)
else
node.left_c = Node.new(value)
end
end
end
get(node, value)
end
def delete (value)
node = @root
parent = @root
while node
if node.data.to_i < value
parent = node
node = node.right_c
elsif node.data.to_i > value
parent = node
node = node.left_c
# ERASING LEAF NODES
elsif node.data == value && node.left_c == nil && node.right_c == nil
if parent.data > value
parent.left_c = nil
node = node.left_c
elsif parent.data < value
parent.right_c = nil
node = node.right_c
end
#ERASING NODES with just ONE CHILD in the LEFT
elsif node.data == value && node.left_c && node.right_c ==nil
parent.left_c = node.left_c
node = node.right_c
#ERASING nodes with just ONE CHILD in the RIGHT
elsif node.data == value && node.left_c == nil && node.right_c
parent.right_c = node.right_c
node = node.right_c
#Erasing NODEs with TWO children
elsif node.data == value && node.left_c && node.right_c
hold = node.right_c
target = node
while hold
if !hold.left_c
target = hold
delete(target.data)
node.data = target.data
break
elsif hold.left_c
hold = hold.left_c
end
end
end
end
end
def find(value)
node = @root
while node
if node.data < value && node.right_c
node = node.right_c
elsif node.data > value && node.left_c
node = node.left_c
elsif node.data == value
puts "This is the node with value #{value}: #{node}"
break
elsif (node.data > value && node.left_c==nil) || (node.data < value && node.left_c==nil)
puts "There is no node with value of #{value} in this Tree"
break
end
end
end
def level_order
queue = []
result = []
node = @root
#starting putting the root in queue
queue.push(node)
while node
#check if got children and put them in the queue from left to right
queue.push(node.left_c) if node.left_c
queue.push(node.right_c) if node.right_c
#when finished the level push the nodes into the Array and yield them (ha!)
result.push(queue.shift.data)
puts yield result.last if block_given?
#do it again
node = queue.first
end
pp result if !block_given?
end
def inorder(value=root)
#get the lower node
result = []
node = value
recursive_in(node, result)
pp result
result.each {|node| yield node}
end
def recursive_in(node, result)
return result unless node
recursive_in(node.left_c, result) if node.left_c
result << node.data
recursive_in(node.right_c, result) if node.right_c
end
def preorder(value=root)
result = []
node = value
recursive_pre(node, result)
pp result
result.each {|node| yield node}
end
def recursive_pre(node, result)
return result unless node
result << node.data
recursive_pre(node.left_c, result) if node.left_c
recursive_pre(node.right_c, result) if node.right_c
end
def postorder(value=root)
result = []
node = value
recursive_post(node, result)
pp result
result.each {|node| yield node}
end
def recursive_post(node, result)
return result unless node
recursive_post(node.left_c, result) if node.left_c
recursive_post(node.right_c, result) if node.right_c
result << node.data
end
def depth(value, node = @root)
depth = 0
while node
if node.data < value && node.right_c
node = node.right_c
depth += 1
elsif node.data > value && node.left_c
node = node.left_c
depth += 1
elsif node.data == value
pp depth
return depth
elsif (node.data > value && node.left_c==nil) || (node.data < value && node.left_c==nil)
puts "There is no node with value of #{value} in this Tree"
break
end
end
end
#AHORA MISMO ESTAMOS LIDIANDO SOLO CON ESTE METHODO... EL DE BALANCED.
def balanced?
node = @root
a_node = node.left_c
b_node = node.right_c
left_depth = leaf_node(a_node)
right_depth = leaf_node(b_node)
if (depth(left_depth.data, a_node) - depth(right_depth.data, b_node) < 1) && (depth(left_depth.data, a_node) - depth(right_depth.data, b_node) > -1)
puts "It is balanced"
else
puts "It is not balanced"
end
end
def leaf_node(node)
return node unless (node.left_c && node.right_c)
leaf_node(node.left_c) if node.left_c
leaf_node(node.right_c) if node.right_c
end
def rebalance!
array = level_order()
pp "array es #{array}"
tree = build_tree(array)
pp tree
end
end
#1. Create a binary search tree from an array of random numbers (`Array.new(15) { rand(1..100) }`)
array = Array.new(15) {rand(1..100)}
tree = Tree.new(array)
#2. Confirm that the tree is balanced by calling `#balanced?`
tree.balanced?
#3. Print out all elements in level, pre, post, and in order
tree.level_order {|node| "I'm yielding the data of this node which is: #{node} "}
tree.inorder { |node| puts "I am yieldin the node of value #{node} "}
tree.preorder { |node| puts "I am yieldin the node of value #{node} "}
tree.postorder { |node| puts "I am yieldin the node of value #{node} "}
#4. try to unbalance the tree by adding several numbers > 100
10.times {tree.insert(rand(0..1000000))}
pp tree
#5. Confirm that the tree is unbalanced by calling `#balanced?`
tree.balanced?
#6. Balance the tree by calling `#rebalance!`
tree.rebalance!
#7. Confirm that the tree is balanced by calling `#balanced?`
tree.balanced?
#8. Print out all elements in level, pre, post, and in order
tree.level_order {|node| "I'm yielding the data of this node which is: #{node} "}
tree.inorder { |node| puts "I am yieldin the node of value #{node} "}
tree.preorder { |node| puts "I am yieldin the node of value #{node} "}
tree.postorder { |node| puts "I am yieldin the node of value #{node} "}