-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbinary_search_tree.go
241 lines (221 loc) · 5.53 KB
/
binary_search_tree.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
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
package main
import (
"errors"
"fmt"
)
// TreeNode represents a node in the binary search tree.
type TreeNode struct {
Key int
Left *TreeNode
Right *TreeNode
Parent *TreeNode
Size int // Size of the subtree, including this node.
}
// BinarySearchTree represents the binary search tree structure.
type BinarySearchTree struct {
Root *TreeNode
}
// NewTreeNode creates a new tree node.
func NewTreeNode(key int) *TreeNode {
return &TreeNode{
Key: key,
Size: 1, // A single node has size 1.
}
}
// Insert adds a new key to the BST. Ignores duplicates.
func (bst *BinarySearchTree) Insert(key int) {
if bst.Search(key) != nil {
return // Ignore duplicates.
}
newNode := NewTreeNode(key)
if bst.Root == nil {
bst.Root = newNode
return
}
current := bst.Root
for current != nil {
current.Size++ // Update size of the subtree.
if key < current.Key {
if current.Left == nil {
current.Left = newNode
newNode.Parent = current
bst.updateSize(current)
return
}
current = current.Left
} else {
if current.Right == nil {
current.Right = newNode
newNode.Parent = current
bst.updateSize(current)
return
}
current = current.Right
}
}
}
// Search finds a node with the given key in the BST.
func (bst *BinarySearchTree) Search(key int) *TreeNode {
current := bst.Root
for current != nil {
if key == current.Key {
return current
} else if key < current.Key {
current = current.Left
} else {
current = current.Right
}
}
return nil
}
// Minimum finds the node with the smallest key in the BST or subtree.
func (bst *BinarySearchTree) Minimum(node *TreeNode) *TreeNode {
if node == nil {
node = bst.Root
}
for node != nil && node.Left != nil {
node = node.Left
}
return node
}
// Maximum finds the node with the largest key in the BST or subtree.
func (bst *BinarySearchTree) Maximum(node *TreeNode) *TreeNode {
if node == nil {
node = bst.Root
}
for node != nil && node.Right != nil {
node = node.Right
}
return node
}
// Successor finds the next largest key after the given key.
func (bst *BinarySearchTree) Successor(key int) (*int, error) {
node := bst.Search(key)
if node == nil {
return nil, errors.New("key not found")
}
if node.Right != nil {
min := bst.Minimum(node.Right)
return &min.Key, nil
}
current := node.Parent
for current != nil && node == current.Right {
node = current
current = current.Parent
}
if current == nil {
return nil, errors.New("no successor found")
}
return ¤t.Key, nil
}
// Predecessor finds the next smaller key before the given key.
func (bst *BinarySearchTree) Predecessor(key int) (*int, error) {
node := bst.Search(key)
if node == nil {
return nil, errors.New("key not found")
}
if node.Left != nil {
max := bst.Maximum(node.Left)
return &max.Key, nil
}
current := node.Parent
for current != nil && node == current.Left {
node = current
current = current.Parent
}
if current == nil {
return nil, errors.New("no predecessor found")
}
return ¤t.Key, nil
}
// Delete removes a node with the given key from the BST.
func (bst *BinarySearchTree) Delete(key int) error {
node := bst.Search(key)
if node == nil {
return errors.New("key not found")
}
if node.Left == nil && node.Right == nil { // Case 1: No children.
bst.transplant(node, nil)
} else if node.Right == nil { // Case 2: One child (left).
bst.transplant(node, node.Left)
} else if node.Left == nil { // Case 2: One child (right).
bst.transplant(node, node.Right)
} else { // Case 3: Two children.
successor := bst.Minimum(node.Right)
if successor.Parent != node {
bst.transplant(successor, successor.Right)
successor.Right = node.Right
successor.Right.Parent = successor
}
bst.transplant(node, successor)
successor.Left = node.Left
successor.Left.Parent = successor
successor.Size = node.Size
}
bst.updateSize(node.Parent) // Update sizes up the tree.
return nil
}
// transplant replaces one subtree with another.
func (bst *BinarySearchTree) transplant(u, v *TreeNode) {
if u.Parent == nil {
bst.Root = v
} else if u == u.Parent.Left {
u.Parent.Left = v
} else {
u.Parent.Right = v
}
if v != nil {
v.Parent = u.Parent
}
}
// updateSize updates the sizes of all ancestor nodes.
func (bst *BinarySearchTree) updateSize(node *TreeNode) {
for node != nil {
node.Size = 1
if node.Left != nil {
node.Size += node.Left.Size
}
if node.Right != nil {
node.Size += node.Right.Size
}
node = node.Parent
}
}
// InOrderTraversal returns the keys in sorted order.
func (bst *BinarySearchTree) InOrderTraversal() []int {
var result []int
var inOrder func(node *TreeNode)
inOrder = func(node *TreeNode) {
if node == nil {
return
}
inOrder(node.Left)
result = append(result, node.Key)
inOrder(node.Right)
}
inOrder(bst.Root)
return result
}
// Main function to demonstrate the BinarySearchTree operations.
func main() {
bst := &BinarySearchTree{}
// Insert keys.
bst.Insert(15)
bst.Insert(10)
bst.Insert(20)
bst.Insert(8)
bst.Insert(12)
// In-order traversal.
fmt.Println("In-order Traversal:", bst.InOrderTraversal())
// Find minimum and maximum.
fmt.Println("Minimum:", bst.Minimum(nil).Key)
fmt.Println("Maximum:", bst.Maximum(nil).Key)
// Find successor and predecessor.
successor, _ := bst.Successor(10)
fmt.Println("Successor of 10:", *successor)
predecessor, _ := bst.Predecessor(15)
fmt.Println("Predecessor of 15:", *predecessor)
// Delete a node and display updated tree.
_ = bst.Delete(10)
fmt.Println("In-order Traversal after deleting 10:", bst.InOrderTraversal())
}