-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbinary_search_tree.rb
105 lines (81 loc) · 1.74 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
class Node
attr_accessor :leftNode, :rightNode, :rightCount, :leftCount
def initialize(value)
@value = value
@rightCount = 0
@leftCount = 0
@same = 0
end
# rotates tree and returns new root if needed
def balanceTree
if @leftCount > @rightCount*2
return rotateLeft
elsif @rightCount > @leftCount*2
return rotateRight
end
return self
end
def rotateLeft
node = @leftNode
@leftNode = @leftNode.rightNode
@leftCount = node.rightCount
node.rightNode = self
node.rightCount = length
node
end
def rotateRight
node = @rightNode
@rightNode = @rightNode.leftNode
@rightCount = node.leftCount
node.leftNode = self
node.leftCount = length
node
end
def value
@value
end
def length
@rightCount + @leftCount + 1 + @same
end
def link(node)
res = 0
if node.value < @value
res = linkToNode('leftNode', node)
res += @rightCount + 1 + @same
@leftCount += 1
elsif node.value > @value
res = linkToNode('rightNode', node)
@rightCount += 1
elsif node.value == @value
@same += 1
res = @rightCount
end
@rightNode = @rightNode.balanceTree if @rightNode
@leftNode = @leftNode.balanceTree if @leftNode
return res
end
private
def linkToNode(linkNodeName, node)
res = 0
linkNode = instance_variable_get("@#{linkNodeName}")
if linkNode
res = linkNode.link(node)
else
instance_variable_set("@#{linkNodeName}", node)
end
return res
end
end
class Tree
def initialize(value)
node = Node.new(value)
@rootNode = node
end
def add(value)
node = Node.new(value)
@rootNode.link node
end
def length
@rootNode.length
end
end