Skip to content

Commit 62bfb1f

Browse files
committed
AVLTree augmentation, modify getindex, works in O(log n) now
1 parent e95887d commit 62bfb1f

File tree

1 file changed

+36
-13
lines changed

1 file changed

+36
-13
lines changed

src/avl_tree.jl

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@ mutable struct AVLTreeNode{K}
66
height::Int8
77
leftChild::Union{AVLTreeNode{K}, Nothing}
88
rightChild::Union{AVLTreeNode{K}, Nothing}
9+
subsize::Int32
910
data::K
1011

11-
AVLTreeNode{K}(d::K) where K = new{K}(1, nothing, nothing, d)
12+
AVLTreeNode{K}(d::K) where K = new{K}(1, nothing, nothing, 1, d)
1213
end
1314

1415
AVLTreeNode(d) = AVLTreeNode{Any}(d)
@@ -41,6 +42,19 @@ end
4142
# one added the maximum of the height of the left subtree and right subtree
4243
compute_height(node::AVLTreeNode) = 1 + max(get_height(node.leftChild), get_height(node.rightChild))
4344

45+
get_subsize(node::AVLTreeNode_or_null) = (node == nothing) ? 0 : node.subsize
46+
47+
# compute the subtree size
48+
function compute_subtree_size(node::AVLTreeNode_or_null)
49+
if node == nothing
50+
return 0
51+
else
52+
L = get_subsize(node.leftChild)
53+
R = get_subsize(node.rightChild)
54+
return (L + R + 1)
55+
end
56+
end
57+
4458
"""
4559
left_rotate(node_x::AVLTreeNode)
4660
@@ -53,6 +67,8 @@ function left_rotate(z::AVLTreeNode)
5367
z.rightChild = α
5468
z.height = compute_height(z)
5569
y.height = compute_height(y)
70+
z.subsize = compute_subtree_size(z)
71+
y.subsize = compute_subtree_size(y)
5672
return y
5773
end
5874

@@ -68,6 +84,8 @@ function right_rotate(z::AVLTreeNode)
6884
z.leftChild = α
6985
z.height = compute_height(z)
7086
y.height = compute_height(y)
87+
z.subsize = compute_subtree_size(z)
88+
y.subsize = compute_subtree_size(y)
7189
return y
7290
end
7391

@@ -118,6 +136,7 @@ function Base.insert!(tree::AVLTree{K}, d::K) where K
118136
node.rightChild = insert_node(node.rightChild, key)
119137
end
120138

139+
node.subsize = compute_subtree_size(node)
121140
node.height = compute_height(node)
122141
balance = get_balance(node)
123142

@@ -176,7 +195,8 @@ function Base.delete!(tree::AVLTree{K}, d::K) where K
176195
node.rightChild = delete_node!(node.rightChild, result.data)
177196
end
178197
end
179-
198+
199+
node.subsize = compute_subtree_size(node)
180200
node.height = compute_height(node)
181201
balance = get_balance(node)
182202

@@ -197,7 +217,7 @@ function Base.delete!(tree::AVLTree{K}, d::K) where K
197217
return left_rotate(node)
198218
end
199219
end
200-
220+
201221
return node
202222
end
203223

@@ -210,17 +230,20 @@ function Base.delete!(tree::AVLTree{K}, d::K) where K
210230
return tree
211231
end
212232

213-
function Base.getindex(tree::AVLTree{K}, ind) where K
233+
function Base.getindex(tree::AVLTree{K}, ind::Integer) where K
214234
@boundscheck (1 <= ind <= tree.count) || throw(BoundsError("$ind should be in between 1 and $(tree.count)"))
215-
function traverse_tree_inorder(node::Union{AVLTreeNode, Nothing})
235+
function traverse_tree(node::AVLTreeNode_or_null, idx)
216236
if (node != nothing)
217-
left = traverse_tree_inorder(node.leftChild)
218-
right = traverse_tree_inorder(node.rightChild)
219-
append!(push!(left, node.data), right)
220-
else
221-
return K[]
237+
L = get_subsize(node.leftChild)
238+
if idx <= L
239+
return traverse_tree(node.leftChild, idx)
240+
elseif idx == L + 1
241+
return node.data
242+
else
243+
return traverse_tree(node.rightChild, idx - L - 1)
244+
end
222245
end
223246
end
224-
arr = traverse_tree_inorder(tree.root)
225-
return @inbounds arr[ind]
226-
end
247+
value = traverse_tree(tree.root, ind)
248+
return value
249+
end

0 commit comments

Comments
 (0)