forked from codeunion/data-structures
-
Notifications
You must be signed in to change notification settings - Fork 0
/
binary_search_tree.rb
133 lines (113 loc) · 2.81 KB
/
binary_search_tree.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
require_relative "binary_tree"
# Implement a binary search tree.
# See http://en.wikipedia.org/wiki/Binary_search_tree
# Operations to support:
# include?(value) Average O(log n) time
# insert(value) Average O(log n) time
# remove(value) Average O(log n) time
# empty? O(1) time
class BinarySearchTree < BinaryTree
def self.empty
EmptyBinarySearchTree.new
end
def initialize(value, left = :empty, right = :empty)
@value = value
@left = EmptyBinarySearchTree.new(left)
@right = EmptyBinarySearchTree.new(right)
end
def include?(value)
return true if value == self.value
if value < self.value
return false if self.left.empty?
self.left.include?(value)
elsif value > self.value
return false if self.right.empty?
self.right.include?(value)
end
end
def insert(value)
if value < self.value
if self.left.empty?
self.left = BinarySearchTree.new(value)
else
self.left.insert(value)
end
elsif value > self.value
if self.right.empty?
self.right = BinarySearchTree.new(value)
else
self.right.insert(value)
end
end
self
end
# Look for max value that is smaller than value to be removed and replace
# removed value with that max value. Max tree should be replaced with
# EmptyTree if leaf or with left node if that node holds a value.
def remove(value)
if value < self.value
self.left = self.left.remove(value) if self.has_left_child?
return self
elsif value > self.value
self.right = self.right.remove(value) if self.has_right_child?
return self
end
# +self+ is the node we want to remove
case self.children_count
when 0
BinarySearchTree.empty
when 1
if self.has_left_child?
self.left
elsif self.has_right_child?
self.right
end
when 2
left_max = self.left.max.value
self.value = left_max
self.left = left.remove(left_max)
self
end
end
def has_left_child?
self.left.empty? ? false : true
end
def has_right_child?
self.right.empty? ? false : true
end
def empty?
false
end
def children_count
if left.empty? && right.empty?
0
elsif left.empty? || right.empty?
1
elsif !left.empty? && !right.empty?
2
end
end
def min
return self if self.left.empty?
self.left.max
end
def max
return self if self.right.empty?
self.right.max
end
end
class EmptyBinarySearchTree < BinarySearchTree
def initialize(value = :empty, left = :empty, right = :empty)
@value = :empty
@left = :empty
@right = :empty
end
def pre_order(&block); end
def in_order(&block); end
def post_order(&block); end
def min; end
def max; end
def empty?
true
end
end