-
Notifications
You must be signed in to change notification settings - Fork 0
/
rbtree.go
141 lines (111 loc) · 2 KB
/
rbtree.go
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
package rbtree
const (
RED = true
BLACK = false
)
type RedBlackTree struct {
root *Node
}
type Item interface {
Less(than Item) bool
More(than Item) bool
}
type Node struct {
size uint64
left, right *Node
item Item
value string
color bool
}
func New() *RedBlackTree {
return &RedBlackTree{}
}
func (t *RedBlackTree) Size() uint64 {
return t.root.Size()
}
func (n *RedBlackTree) Put(key Item) {
n.root = put(n.root, key)
n.root.color = BLACK
}
func (n *RedBlackTree) Find(key Item) (Item, bool) {
return find(n.root, key)
}
func (n *Node) Size() uint64 {
return n.size
}
func (n *Node) Item() Item {
return n.item
}
func size(n *Node) uint64 {
if n == nil {
return 0
}
return n.size
}
func put(n *Node, item Item) *Node {
switch {
case n == nil:
return &Node{item: item, size: 1, color: RED}
case item.Less(n.item):
n.left = put(n.left, item)
case n.item.Less(item):
n.right = put(n.right, item)
default:
n.item = item
}
if !isRed(n.left) && isRed(n.right) {
n = rotateLeft(n)
}
if isRed(n.left) && isRed(n.left.left) {
n = rotateRight(n)
}
if isRed(n.left) && isRed(n.right) {
changeColors(n)
}
n.size = size(n.left) + size(n.right) + 1
return n
}
func find(n *Node, item Item) (Item, bool) {
switch {
case n == nil:
return nil, false
case item.Less(n.item):
return find(n.left, item)
case item.More(n.item):
return find(n.right, item)
default:
return n.Item(), true
}
return nil, false
}
func rotateLeft(n *Node) *Node {
x := n.right
n.right = x.left
x.left = n
x.color = n.color
n.color = RED
x.size = n.size
n.size = size(n.left) + size(n.right) + 1
return x
}
func rotateRight(n *Node) *Node {
x := n.left
n.left = x.right
x.right = n
x.color = n.color
n.color = RED
x.size = n.size
n.size = size(n.left) + size(n.right) + 1
return x
}
func changeColors(n *Node) {
n.left.color = BLACK
n.right.color = BLACK
n.color = RED
}
func isRed(n *Node) bool {
if n == nil {
return false
}
return n.color
}