forked from tokihiro000/Crawler
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrbt.rb
166 lines (144 loc) · 3.41 KB
/
rbt.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
# -*- coding: utf-8 -*-
=begin
Red_Black_Treeを構成するクラスです。
今のところ挿入、検索、挿入時回転のみが実装されています。
削除と削除時回転は後で実装します。
参考サイト:
[http://www.geocities.jp/m_hiroi/light/abcruby13.html]
こちらはただの2分探索ですが、ひな形として使わせていただきました。
=end
class Red_Black_Tree
class Node
def initialize(key, data, color)
@key = key
@data = data
@color = color
@left = nil
@right = nil
end
attr_accessor :key, :data, :color, :left, :right
end
def initialize
@root = nil
end
# ここからのメソッドはprivate
private
def isRed(node)
if node != nil && (node.color == 0)
return 1
else
return 0
end
end
def isBlack(node)
if node != nil && (node.color = 1)
return 1
else
return 0
end
end
#部分木の回転。左回転
def LeftRotation(node)
rl_node = node.right.left
r_node = node.right
r_node.left = node
r_node.left.right = rl_node
return r_node
end
#部分木の回転。右回転
def RightRotation(node)
lr_node = node.left.right
l_node = node.left
l_node.right = node
l_node.right.left = lr_node
return l_node
end
#部分木の2重回転。左回転→右回転
def LRRotation(node)
node.left = LeftRotation(node.left)
return RightRotation(node)
end
#部分木の2重回転。右回転→左回転
def RLRotation(node)
node.right = RightRotation(node.right)
return LeftRotation(node)
end
#挿入時の赤黒木修正
def KeepTreesBalance(node)
if node.color != 1
return node
elsif isRed(node.left) == 1 && isRed(node.left.left) == 1
node = RightRotation(node)
node.left.color = 1
elsif isRed(node.left) == 1 && isRed(node.left.right) == 1
node = LRRotation(node)
node.left.color = 1
elsif isRed(node.right) == 1 && isRed(node.right.left) == 1
node = RLRotation(node)
node.right.color = 1
elsif isRed(node.right) == 1 && isRed(node.right.right) == 1
node = LeftRotation(node)
node.right.color = 1
end
return node
end
# 探索
def search(node, key)
while node
if key == node.key
return node
elsif key < node.key
node = node.left
else
node = node.right
end
end
return nil
end
# 挿入
def insert_node(node, key, data)
if node == nil
return Node.new(key, data, 0)
elsif key == node.key
node.data = data
return node
elsif key < node.key
node.left = insert_node(node.left, key, data)
new_tree = KeepTreesBalance(node)
return new_tree
elsif key > node.key
node.right = insert_node(node.right, key, data)
new_tree = KeepTreesBalance(node)
return new_tree
end
end
# ここからのメソッドはpublic
public
# ユーザが使う探索メソッド
def [](key)
node = search(@root, key)
if node
return node.data
else
return nil
end
end
# ユーザが使う挿入メソッド
def []=(key, data)
@root = insert_node(@root, key, data)
@root.color = 1
return data
end
end
if __FILE__ == $0
t = Red_Black_Tree.new
10.times do |x|
t[x+1]=(x+1)*100
end
10.times do |x|
t[x+1]=(x+1)*100
end
10.times do |x|
print t[x+1], "\n"
end
end