Skip to content

Commit ee54fe4

Browse files
committed
Add index operations for AVL tree
1 parent 470bfa7 commit ee54fe4

File tree

4 files changed

+93
-15
lines changed

4 files changed

+93
-15
lines changed

src/Advanced.Algorithms/DataStructures/Tree/AvlTree.cs

Lines changed: 68 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public AVLTree(bool enableNodeLookUp = false)
3333
/// <param name="sortedKeys">The sorted keys.</param>
3434
/// <param name="enableNodeLookUp">Enabling lookup will fasten deletion/insertion/exists operations
3535
/// at the cost of additional space.</param>
36-
public AVLTree(IEnumerable<T> sortedKeys, bool enableNodeLookUp = false)
36+
public AVLTree(IEnumerable<T> sortedKeys, bool enableNodeLookUp = false)
3737
: this(enableNodeLookUp)
3838
{
3939
ValidateCollection(sortedKeys);
@@ -43,7 +43,7 @@ public AVLTree(IEnumerable<T> sortedKeys, bool enableNodeLookUp = false)
4343
assignCount(Root);
4444
}
4545

46-
46+
4747
/// <summary>
4848
/// Time complexity: O(log(n))
4949
/// </summary>
@@ -139,6 +139,25 @@ private void insert(AVLTreeNode<T> node, T value)
139139
node.UpdateCounts();
140140
}
141141

142+
/// <summary>
143+
/// </summary>
144+
public int IndexOf(T item)
145+
{
146+
return Root.Position(item);
147+
}
148+
149+
/// <summary>
150+
/// Time complexity: O(log(n))
151+
/// </summary>
152+
public T ElementAt(int index)
153+
{
154+
if (index < 0 || index >= Count)
155+
{
156+
throw new ArgumentNullException("index");
157+
}
158+
159+
return Root.KthSmallest(index).Value;
160+
}
142161

143162
/// <summary>
144163
/// Time complexity: O(log(n)).
@@ -159,8 +178,37 @@ public void Delete(T value)
159178

160179
}
161180

162-
163-
private void delete(AVLTreeNode<T> node, T value)
181+
/// <summary>
182+
/// Time complexity: O(log(n))
183+
/// </summary>
184+
public T RemoveAt(int index)
185+
{
186+
if (index < 0 || index >= Count)
187+
{
188+
throw new ArgumentException("index");
189+
}
190+
191+
var nodeToDelete = Root.KthSmallest(index) as AVLTreeNode<T>;
192+
var nodeToBalance = delete(nodeToDelete, nodeToDelete.Value);
193+
194+
while (nodeToBalance != null)
195+
{
196+
nodeToBalance.UpdateCounts();
197+
updateHeight(nodeToBalance);
198+
balance(nodeToBalance);
199+
200+
nodeToBalance = nodeToBalance.Parent;
201+
}
202+
203+
if (nodeLookUp != null)
204+
{
205+
nodeLookUp.Remove(nodeToDelete.Value);
206+
}
207+
208+
return nodeToDelete.Value;
209+
}
210+
211+
private AVLTreeNode<T> delete(AVLTreeNode<T> node, T value)
164212
{
165213
var baseCase = false;
166214

@@ -289,14 +337,15 @@ private void delete(AVLTreeNode<T> node, T value)
289337
node.Parent.UpdateCounts();
290338
updateHeight(node.Parent);
291339
balance(node.Parent);
340+
return node.Parent;
292341
}
293342
else
294343
{
295344
node.UpdateCounts();
296345
updateHeight(node);
297346
balance(node);
347+
return node;
298348
}
299-
300349
}
301350

302351
/// <summary>
@@ -307,7 +356,6 @@ public T FindMax()
307356
return findMax(Root).Value;
308357
}
309358

310-
311359
private AVLTreeNode<T> findMax(AVLTreeNode<T> node)
312360
{
313361
while (true)
@@ -565,7 +613,7 @@ private void updateHeight(AVLTreeNode<T> node)
565613

566614
private void recomputeHeight(AVLTreeNode<T> node)
567615
{
568-
if(node == null)
616+
if (node == null)
569617
{
570618
return;
571619
}
@@ -629,6 +677,19 @@ internal void Swap(T value1, T value2)
629677
}
630678
}
631679

680+
/// <summary>
681+
/// Descending enumerable.
682+
/// </summary>
683+
public IEnumerable<T> AsEnumerableDesc()
684+
{
685+
return GetEnumeratorDesc().AsEnumerable();
686+
}
687+
688+
public IEnumerator<T> GetEnumeratorDesc()
689+
{
690+
return new BSTEnumerator<T>(Root, false);
691+
}
692+
632693
//Implementation for the GetEnumerator method.
633694
IEnumerator IEnumerable.GetEnumerator()
634695
{

src/Advanced.Algorithms/DataStructures/Tree/RedBlackTree.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ public T RemoveAt(int index)
381381
{
382382
if (index < 0 || index >= Count)
383383
{
384-
throw new ArgumentNullException("index");
384+
throw new ArgumentException("index");
385385
}
386386

387387
var node = Root.KthSmallest(index) as RedBlackTreeNode<T>;

tests/Advanced.Algorithms.Tests/DataStructures/Tree/AVLTree_Tests.cs

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -99,17 +99,18 @@ public void AVLTree_Accuracy_Test()
9999
var nodeCount = 1000;
100100

101101
var rnd = new Random();
102-
var sortedNumbers = Enumerable.Range(1, nodeCount)
102+
var sorted = Enumerable.Range(1, nodeCount).ToList();
103+
var randomNumbers = sorted
103104
.OrderBy(x => rnd.Next())
104105
.ToList();
105106

106107
var tree = new AVLTree<int>(true);
107108

108109
for (int i = 0; i < nodeCount; i++)
109110
{
110-
tree.Insert(sortedNumbers[i]);
111+
tree.Insert(randomNumbers[i]);
111112

112-
Assert.IsTrue(tree.HasItem(sortedNumbers[i]));
113+
Assert.IsTrue(tree.HasItem(randomNumbers[i]));
113114
Assert.IsTrue(tree.Root.IsBinarySearchTree(int.MinValue, int.MaxValue));
114115
tree.Root.VerifyCount();
115116

@@ -122,19 +123,35 @@ public void AVLTree_Accuracy_Test()
122123
Assert.IsTrue(tree.Count == i + 1);
123124
}
124125

125-
sortedNumbers = Enumerable.Range(1, nodeCount)
126+
for (int i = 0; i < sorted.Count; i++)
127+
{
128+
Assert.AreEqual(sorted[i], tree.ElementAt(i));
129+
Assert.AreEqual(i, tree.IndexOf(sorted[i]));
130+
}
131+
132+
randomNumbers = Enumerable.Range(1, nodeCount)
126133
.OrderBy(x => rnd.Next())
127134
.ToList();
128135

129136
//IEnumerable test using linq
130137
Assert.AreEqual(tree.Count, tree.Count());
138+
Assert.AreEqual(tree.Count, tree.AsEnumerableDesc().Count());
131139

132140
for (int i = 0; i < nodeCount; i++)
133141
{
134-
tree.Delete(sortedNumbers[i]);
142+
if (rnd.NextDouble() >= 0.5)
143+
{
144+
tree.Delete(randomNumbers[i]);
145+
}
146+
else
147+
{
148+
var index = tree.IndexOf(randomNumbers[i]);
149+
Assert.AreEqual(tree.ElementAt(index), randomNumbers[i]);
150+
tree.RemoveAt(index);
151+
}
135152

136-
tree.Root.VerifyCount();
137153
Assert.IsTrue(tree.Root.IsBinarySearchTree(int.MinValue, int.MaxValue));
154+
tree.Root.VerifyCount();
138155

139156
var actualHeight = tree.GetHeight();
140157

tests/Advanced.Algorithms.Tests/DataStructures/Tree/RedBlackTree_Tests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,6 @@ public void RedBlackTree_Accuracy_Test()
8787
Assert.AreEqual(i, tree.IndexOf(sorted[i]));
8888
}
8989

90-
9190
//shuffle again before deletion tests
9291
randomNumbers = Enumerable.Range(1, nodeCount)
9392
.OrderBy(x => rnd.Next())
@@ -106,6 +105,7 @@ public void RedBlackTree_Accuracy_Test()
106105
else
107106
{
108107
var index = tree.IndexOf(randomNumbers[i]);
108+
Assert.AreEqual(tree.ElementAt(index), randomNumbers[i]);
109109
tree.RemoveAt(index);
110110
}
111111

0 commit comments

Comments
 (0)