@@ -61,175 +61,221 @@ module AVLTree =
6161
6262 let empty = { Root = None }
6363
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+
64220 let insert ( value : int ) ( tree : AVLTree ) : AVLTree =
65221 let rec insertImpl ( maybeNode : Option < AVLNode >) : AVLNode =
66222 match maybeNode with
67223 | None ->
68224 AVLNode.create value
69225 | 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
230230 node
231+ else
232+ node.UpdateRightChild ( Some ( insertImpl node.RightChild))
233+ |> rebalance
231234
232235
233236 insertImpl tree.Root
234237 |> fun root -> { Root = Some root }
235238
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