Skip to content

Commit 0f61b35

Browse files
committed
implement delete
1 parent 8269cba commit 0f61b35

File tree

1 file changed

+206
-160
lines changed

1 file changed

+206
-160
lines changed

Algorithms/DataStructures/AVLTree.fs

Lines changed: 206 additions & 160 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)