@@ -61,175 +61,221 @@ module AVLTree =
61
61
62
62
let empty = { Root = None }
63
63
64
+ let private rebalance ( node : AVLNode ) : AVLNode =
65
+ if AVLNode.balanceFactor node > 1 then
66
+ // Root node is right heavy, current balance factor is 2
67
+ // check the balance factor of the right child
68
+ if node.RightChild |> Option.get |> AVLNode.balanceFactor < 0 then
69
+ // Right child is left heavy
70
+ // rotate right around right child and rotate left around root
71
+
72
+ // Illustration: possible heights are shown in brackets,
73
+ // and the balance factor of the node is shown in parentheses
74
+
75
+ // Initial state:
76
+ //
77
+ // b (+2) [h+3]
78
+ // / \
79
+ // [h] a f (-1) [h+2]
80
+ // /\
81
+ // [h+1] (0|-1|+1) d g [h]
82
+ // /\
83
+ // [h|h-1] c e [h|h-1]
84
+
85
+ // rotate right around f (right child)
86
+ //
87
+ // b (+2) [h+3]
88
+ // / \
89
+ // [h] a d (+1|+2) [h+2]
90
+ // /\
91
+ // [h|h-1] c f (0|-1) [h+1]
92
+ // /\
93
+ // [h|h-1] e g [h]
94
+
95
+ // rotate left around b (root)
96
+ // d (0) [h+2]
97
+ // __________/\__________
98
+ // / \
99
+ // [h+1] (0|-1) b f (0|-1) [h+1]
100
+ // / \ /\
101
+ // [h] a c [h|h-1] [h|h-1] e g [h]
102
+
103
+
104
+ let node = node.UpdateRightChild ( Some ( AVLTree.rotateRight ( node.RightChild |> Option.get)))
105
+ AVLTree.rotateLeft node
106
+ else
107
+ // Right child is balanced or left heavy,
108
+ // rotate left around root
109
+
110
+ // Illustration if right child is balanced
111
+
112
+ // Initial state:
113
+ // b (+2) [h+3]
114
+ // / \
115
+ // [h] a d (0) [h+2]
116
+ // /\
117
+ // [h+1] c e [h+1]
118
+
119
+ // rotate left around b (root)
120
+ // d (-1) [h+3]
121
+ // / \
122
+ // [h+2] (+1) b e [h+1]
123
+ // / \
124
+ // [h] a c [h+1]
125
+
126
+ // Illustration if right child is right heavy
127
+
128
+ // Initial state:
129
+ // b (+2) [h+3]
130
+ // / \
131
+ // [h] a d (+1) [h+2]
132
+ // /\
133
+ // [h] c e [h+1]
134
+
135
+ // rotate left around b (root)
136
+ // d (0) [h+2]
137
+ // / \
138
+ // [h+1] (0) b e [h+1]
139
+ // / \
140
+ // [h] a c [h]
141
+
142
+ AVLTree.rotateLeft node
143
+ elif AVLNode.balanceFactor node < - 1 then
144
+ // Root node is left heavy, current balance factor is -2
145
+ // check the balance factor of the left child
146
+ if node.LeftChild |> Option.get |> AVLNode.balanceFactor > 0 then
147
+ // Left child is right heavy
148
+ // rotate left around left child and rotate right around root
149
+
150
+ // Initial state:
151
+ // f (-2) [h+3]
152
+ // / \
153
+ // [h+2] (+1) b g [h]
154
+ // /\
155
+ // [h] a d (0|-1|+1) [h+1]
156
+ // /\
157
+ // [h|h-1] c e [h|h-1]
158
+
159
+ // rotate left around b (left child)
160
+ // f (-2) [h+3]
161
+ // / \
162
+ // [h+2] (-2) d g [h]
163
+ // / \
164
+ // [h+1] b e [h|h-1]
165
+ // /\
166
+ // [h] a c [h|h-1]
167
+
168
+ // rotate right around f (root)
169
+ // d (0) [h+2]
170
+ // __________/\__________
171
+ // / \
172
+ // [h+1] (0|-1) b f (0|-1) [h+1]
173
+ // / \ /\
174
+ // [h] a c [h|h-1] [h|h-1] e g [h]
175
+
176
+ let node = node.UpdateLeftChild ( Some ( AVLTree.rotateLeft ( node.LeftChild |> Option.get)))
177
+ AVLTree.rotateRight node
178
+ else
179
+ // Left child is balanced or left heavy
180
+ // rotate right around root
181
+
182
+ // Illustration if left child is balanced
183
+
184
+ // Initial state:
185
+ // d (-2) [h+3]
186
+ // / \
187
+ // [h+2] (0) b e [h]
188
+ // / \
189
+ // [h+1] a c [h+1]
190
+
191
+ // rotate right around d (root)
192
+ // b (+1) [h+3]
193
+ // / \
194
+ // [h+1] a d (-1) [h+2]
195
+ // / \
196
+ // [h+1]c e [h]
197
+
198
+ // Illustration if left child is left heavy
199
+
200
+ // Initial state:
201
+ // d (-2) [h+3]
202
+ // / \
203
+ // [h+2] (-1) b e [h]
204
+ // / \
205
+ // [h+1] a c [h]
206
+
207
+ // rotate right around d (root)
208
+ // b (0) [h+2]
209
+ // / \
210
+ // [h+1] a d (0) [h+1]
211
+ // / \
212
+ // [h] c e [h]
213
+
214
+ AVLTree.rotateRight node
215
+ else
216
+ // Balance of root is within acceptable range
217
+ node
218
+
219
+
64
220
let insert ( value : int ) ( tree : AVLTree ) : AVLTree =
65
221
let rec insertImpl ( maybeNode : Option < AVLNode >) : AVLNode =
66
222
match maybeNode with
67
223
| None ->
68
224
AVLNode.create value
69
225
| Some node ->
70
- let node =
71
- if value < node.Value then
72
- node.UpdateLeftChild ( Some ( insertImpl node.LeftChild))
73
- elif value = node.Value then
74
- node
75
- else
76
- node.UpdateRightChild ( Some ( insertImpl node.RightChild))
77
-
78
- if AVLNode.balanceFactor node > 1 then
79
- // Root node is right heavy, current balance factor is 2
80
- // check the balance factor of the right child
81
- if node.RightChild |> Option.get |> AVLNode.balanceFactor < 0 then
82
- // Right child is left heavy
83
- // rotate right around right child and rotate left around root
84
-
85
- // Illustration: possible heights are shown in brackets,
86
- // and the balance factor of the node is shown in parentheses
87
-
88
- // Initial state:
89
- //
90
- // b (+2) [h+3]
91
- // / \
92
- // [h] a f (-1) [h+2]
93
- // /\
94
- // [h+1] (0|-1|+1) d g [h]
95
- // /\
96
- // [h|h-1] c e [h|h-1]
97
-
98
- // rotate right around f (right child)
99
- //
100
- // b (+2) [h+3]
101
- // / \
102
- // [h] a d (+1|+2) [h+2]
103
- // /\
104
- // [h|h-1] c f (0|-1) [h+1]
105
- // /\
106
- // [h|h-1] e g [h]
107
-
108
- // rotate left around b (root)
109
- // d (0) [h+2]
110
- // __________/\__________
111
- // / \
112
- // [h+1] (0|-1) b f (0|-1) [h+1]
113
- // / \ /\
114
- // [h] a c [h|h-1] [h|h-1] e g [h]
115
-
116
-
117
- let node = node.UpdateRightChild ( Some ( AVLTree.rotateRight ( node.RightChild |> Option.get)))
118
- AVLTree.rotateLeft node
119
- else
120
- // Right child is balanced or left heavy,
121
- // rotate left around root
122
-
123
- // Illustration if right child is balanced
124
-
125
- // Initial state:
126
- // b (+2) [h+3]
127
- // / \
128
- // [h] a d (0) [h+2]
129
- // /\
130
- // [h+1] c e [h+1]
131
-
132
- // rotate left around b (root)
133
- // d (-1) [h+3]
134
- // / \
135
- // [h+2] (+1) b e [h+1]
136
- // / \
137
- // [h] a c [h+1]
138
-
139
- // Illustration if right child is right heavy
140
-
141
- // Initial state:
142
- // b (+2) [h+3]
143
- // / \
144
- // [h] a d (+1) [h+2]
145
- // /\
146
- // [h] c e [h+1]
147
-
148
- // rotate left around b (root)
149
- // d (0) [h+2]
150
- // / \
151
- // [h+1] (0) b e [h+1]
152
- // / \
153
- // [h] a c [h]
154
-
155
- AVLTree.rotateLeft node
156
- elif AVLNode.balanceFactor node < - 1 then
157
- // Root node is left heavy, current balance factor is -2
158
- // check the balance factor of the left child
159
- if node.LeftChild |> Option.get |> AVLNode.balanceFactor > 0 then
160
- // Left child is right heavy
161
- // rotate left around left child and rotate right around root
162
-
163
- // Initial state:
164
- // f (-2) [h+3]
165
- // / \
166
- // [h+2] (+1) b g [h]
167
- // /\
168
- // [h] a d (0|-1|+1) [h+1]
169
- // /\
170
- // [h|h-1] c e [h|h-1]
171
-
172
- // rotate left around b (left child)
173
- // f (-2) [h+3]
174
- // / \
175
- // [h+2] (-2) d g [h]
176
- // / \
177
- // [h+1] b e [h|h-1]
178
- // /\
179
- // [h] a c [h|h-1]
180
-
181
- // rotate right around f (root)
182
- // d (0) [h+2]
183
- // __________/\__________
184
- // / \
185
- // [h+1] (0|-1) b f (0|-1) [h+1]
186
- // / \ /\
187
- // [h] a c [h|h-1] [h|h-1] e g [h]
188
-
189
- let node = node.UpdateLeftChild ( Some ( AVLTree.rotateLeft ( node.LeftChild |> Option.get)))
190
- AVLTree.rotateRight node
191
- else
192
- // Left child is balanced or left heavy
193
- // rotate right around root
194
-
195
- // Illustration if left child is balanced
196
-
197
- // Initial state:
198
- // d (-2) [h+3]
199
- // / \
200
- // [h+2] (0) b e [h]
201
- // / \
202
- // [h+1] a c [h+1]
203
-
204
- // rotate right around d (root)
205
- // b (+1) [h+3]
206
- // / \
207
- // [h+1] a d (-1) [h+2]
208
- // / \
209
- // [h+1]c e [h]
210
-
211
- // Illustration if left child is left heavy
212
-
213
- // Initial state:
214
- // d (-2) [h+3]
215
- // / \
216
- // [h+2] (-1) b e [h]
217
- // / \
218
- // [h+1] a c [h]
219
-
220
- // rotate right around d (root)
221
- // b (0) [h+2]
222
- // / \
223
- // [h+1] a d (0) [h+1]
224
- // / \
225
- // [h] c e [h]
226
-
227
- AVLTree.rotateRight node
228
- else
229
- // Balance of root is within acceptable range
226
+ if value < node.Value then
227
+ node.UpdateLeftChild ( Some ( insertImpl node.LeftChild))
228
+ |> rebalance
229
+ elif value = node.Value then
230
230
node
231
+ else
232
+ node.UpdateRightChild ( Some ( insertImpl node.RightChild))
233
+ |> rebalance
231
234
232
235
233
236
insertImpl tree.Root
234
237
|> fun root -> { Root = Some root }
235
238
239
+ let delete ( value : int ) ( tree : AVLTree ) : AVLTree =
240
+ let rec deleteMinValueNode ( node : AVLNode ) : Option < AVLNode > * (* MinValue *) int =
241
+ match node.LeftChild with
242
+ | None ->
243
+ // delete current node and return the value that was replaced
244
+ node.RightChild, node.Value
245
+ | Some leftChild ->
246
+ let leftChild , minValue = deleteMinValueNode leftChild
247
+ let node =
248
+ node.UpdateLeftChild leftChild
249
+ |> rebalance
250
+ Some node, minValue
251
+
252
+ let rec deleteImpl ( maybeNode : Option < AVLNode >) : Option < AVLNode > =
253
+ match maybeNode with
254
+ | None -> None
255
+ | Some node ->
256
+ if value < node.Value then
257
+ node.UpdateLeftChild ( deleteImpl node.LeftChild)
258
+ |> rebalance
259
+ |> Some
260
+ elif value = node.Value then
261
+ match node.LeftChild, node.RightChild with
262
+ | None, None -> None
263
+ | None, Some rightChild -> Some rightChild
264
+ | Some leftChild, None -> Some leftChild
265
+ | Some leftChild, Some rightChild ->
266
+ let rightNode , currentValue = deleteMinValueNode rightChild
267
+ let node = { node with Value = currentValue }
268
+
269
+ node.UpdateRightChild rightNode
270
+ |> rebalance
271
+ |> Some
272
+ else
273
+ node.UpdateRightChild ( deleteImpl node.RightChild)
274
+ |> rebalance
275
+ |> Some
276
+
277
+
278
+ deleteImpl tree.Root
279
+ |> fun root -> { Root = root }
280
+
281
+
0 commit comments