Skip to content

Commit 9f7ee97

Browse files
committed
index operations on bst
1 parent 825cbca commit 9f7ee97

File tree

6 files changed

+219
-10
lines changed

6 files changed

+219
-10
lines changed

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

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ public void Insert(T value)
8989
newNode.UpdateCounts(true);
9090
}
9191

92+
93+
9294
//worst O(n) for unbalanced tree
9395
private BSTNode<T> insert(BSTNode<T> currentNode, T newNodeValue)
9496
{
@@ -130,6 +132,28 @@ private BSTNode<T> insert(BSTNode<T> currentNode, T newNodeValue)
130132
}
131133
}
132134

135+
// <summary>
136+
/// Time complexity: O(n)
137+
/// </summary>
138+
public int IndexOf(T item)
139+
{
140+
return Root.Position(item);
141+
}
142+
143+
/// <summary>
144+
/// Time complexity: O(n)
145+
/// </summary>
146+
public T ElementAt(int index)
147+
{
148+
if (index < 0 || index >= Count)
149+
{
150+
throw new ArgumentNullException("index");
151+
}
152+
153+
return Root.KthSmallest(index).Value;
154+
}
155+
156+
133157
/// <summary>
134158
/// Time complexity: O(n)
135159
/// </summary>
@@ -144,6 +168,24 @@ public void Delete(T value)
144168
deleted.UpdateCounts(true);
145169
}
146170

171+
/// <summary>
172+
/// Time complexity: O(n)
173+
/// </summary>
174+
public T RemoveAt(int index)
175+
{
176+
if (index < 0 || index >= Count)
177+
{
178+
throw new ArgumentException("index");
179+
}
180+
181+
var nodeToDelete = Root.KthSmallest(index) as BSTNode<T>;
182+
183+
var deleted = delete(nodeToDelete, nodeToDelete.Value);
184+
deleted.UpdateCounts(true);
185+
186+
return nodeToDelete.Value;
187+
}
188+
147189
//worst O(n) for unbalanced tree
148190
private BSTNode<T> delete(BSTNode<T> node, T value)
149191
{
@@ -194,7 +236,7 @@ private BSTNode<T> delete(BSTNode<T> node, T value)
194236
deleteRightNode(node);
195237
return node;
196238
}
197-
239+
198240
//case three - two child trees
199241
//replace the node value with maximum element of left subtree (left max node)
200242
//and then delete the left max node
@@ -388,6 +430,19 @@ public T NextHigher(T value)
388430
return next != null ? next.Value : default(T);
389431
}
390432

433+
/// <summary>
434+
/// Descending enumerable.
435+
/// </summary>
436+
public IEnumerable<T> AsEnumerableDesc()
437+
{
438+
return GetEnumeratorDesc().AsEnumerable();
439+
}
440+
441+
public IEnumerator<T> GetEnumeratorDesc()
442+
{
443+
return new BSTEnumerator<T>(Root, false);
444+
}
445+
391446
//Implementation for the GetEnumerator method.
392447
IEnumerator IEnumerable.GetEnumerator()
393448
{

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

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,27 @@ private SplayTreeNode<T> insert(SplayTreeNode<T> currentNode, T newNodeValue)
113113
}
114114
}
115115

116+
/// <summary>
117+
/// Time complexity: O(log(n))
118+
/// </summary>
119+
public int IndexOf(T item)
120+
{
121+
return Root.Position(item);
122+
}
123+
124+
/// <summary>
125+
/// Time complexity: O(log(n))
126+
/// </summary>
127+
public T ElementAt(int index)
128+
{
129+
if (index < 0 || index >= Count)
130+
{
131+
throw new ArgumentNullException("index");
132+
}
133+
134+
return Root.KthSmallest(index).Value;
135+
}
136+
116137
/// <summary>
117138
/// Time complexity: O(n)
118139
/// </summary>
@@ -126,6 +147,23 @@ public void Delete(T value)
126147
delete(Root, value);
127148
}
128149

150+
/// <summary>
151+
/// Time complexity: O(log(n))
152+
/// </summary>
153+
public T RemoveAt(int index)
154+
{
155+
if (index < 0 || index >= Count)
156+
{
157+
throw new ArgumentException("index");
158+
}
159+
160+
var nodeToDelete = Root.KthSmallest(index) as SplayTreeNode<T>;
161+
162+
delete(nodeToDelete, nodeToDelete.Value);
163+
164+
return nodeToDelete.Value;
165+
}
166+
129167
//O(log(n)) worst O(n) for unbalanced tree
130168
private void delete(SplayTreeNode<T> node, T value)
131169
{
@@ -491,6 +529,19 @@ public T NextHigher(T value)
491529
return next != null ? next.Value : default(T);
492530
}
493531

532+
/// <summary>
533+
/// Descending enumerable.
534+
/// </summary>
535+
public IEnumerable<T> AsEnumerableDesc()
536+
{
537+
return GetEnumeratorDesc().AsEnumerable();
538+
}
539+
540+
public IEnumerator<T> GetEnumeratorDesc()
541+
{
542+
return new BSTEnumerator<T>(Root, false);
543+
}
544+
494545
//Implementation for the GetEnumerator method.
495546
IEnumerator IEnumerable.GetEnumerator()
496547
{

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

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,27 @@ private TreapTreeNode<T> insert(TreapTreeNode<T> currentNode, T newNodeValue)
116116
}
117117
}
118118

119+
/// <summary>
120+
/// Time complexity: O(log(n))
121+
/// </summary>
122+
public int IndexOf(T item)
123+
{
124+
return Root.Position(item);
125+
}
126+
127+
/// <summary>
128+
/// Time complexity: O(log(n))
129+
/// </summary>
130+
public T ElementAt(int index)
131+
{
132+
if (index < 0 || index >= Count)
133+
{
134+
throw new ArgumentNullException("index");
135+
}
136+
137+
return Root.KthSmallest(index).Value;
138+
}
139+
119140
/// <summary>
120141
/// Time complexity: O(log(n))
121142
/// </summary>
@@ -129,6 +150,23 @@ public void Delete(T value)
129150
delete(Root, value);
130151
}
131152

153+
/// <summary>
154+
/// Time complexity: O(log(n))
155+
/// </summary>
156+
public T RemoveAt(int index)
157+
{
158+
if (index < 0 || index >= Count)
159+
{
160+
throw new ArgumentException("index");
161+
}
162+
163+
var nodeToDelete = Root.KthSmallest(index) as TreapTreeNode<T>;
164+
165+
delete(nodeToDelete, nodeToDelete.Value);
166+
167+
return nodeToDelete.Value;
168+
}
169+
132170
//O(log(n)) worst O(n) for unbalanced tree
133171
private void delete(TreapTreeNode<T> node, T value)
134172
{
@@ -486,6 +524,19 @@ public T NextHigher(T value)
486524
return next != null ? next.Value : default(T);
487525
}
488526

527+
/// <summary>
528+
/// Descending enumerable.
529+
/// </summary>
530+
public IEnumerable<T> AsEnumerableDesc()
531+
{
532+
return GetEnumeratorDesc().AsEnumerable();
533+
}
534+
535+
public IEnumerator<T> GetEnumeratorDesc()
536+
{
537+
return new BSTEnumerator<T>(Root, false);
538+
}
539+
489540
//Implementation for the GetEnumerator method.
490541
IEnumerator IEnumerable.GetEnumerator()
491542
{

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

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,8 @@ public void BST_Accuracy_Test()
107107
var nodeCount = 1000;
108108

109109
var rnd = new Random();
110-
var randomNumbers = Enumerable.Range(1, nodeCount)
110+
var sorted = Enumerable.Range(1, nodeCount).ToList();
111+
var randomNumbers = sorted
111112
.OrderBy(x => rnd.Next())
112113
.ToList();
113114

@@ -120,6 +121,11 @@ public void BST_Accuracy_Test()
120121
Assert.IsTrue(tree.Count == i + 1);
121122
}
122123

124+
for (int i = 0; i < sorted.Count; i++)
125+
{
126+
Assert.AreEqual(sorted[i], tree.ElementAt(i));
127+
Assert.AreEqual(i, tree.IndexOf(sorted[i]));
128+
}
123129

124130
//shuffle again before deletion tests
125131
randomNumbers = Enumerable.Range(1, nodeCount)
@@ -128,10 +134,21 @@ public void BST_Accuracy_Test()
128134

129135
//IEnumerable test using linq
130136
Assert.AreEqual(tree.Count, tree.Count());
137+
Assert.AreEqual(tree.Count, tree.AsEnumerableDesc().Count());
131138

132139
for (int i = 0; i < nodeCount; i++)
133140
{
134-
tree.Delete(randomNumbers[i]);
141+
if (rnd.NextDouble() >= 0.5)
142+
{
143+
tree.Delete(randomNumbers[i]);
144+
}
145+
else
146+
{
147+
var index = tree.IndexOf(randomNumbers[i]);
148+
Assert.AreEqual(tree.ElementAt(index), randomNumbers[i]);
149+
tree.RemoveAt(index);
150+
}
151+
135152
tree.Root.VerifyCount();
136153
Assert.IsTrue(tree.Count == nodeCount - 1 - i);
137154
}
@@ -174,6 +191,6 @@ public void BST_Stress_Test()
174191

175192
Assert.IsTrue(tree.Count == 0);
176193
}
177-
194+
178195
}
179196
}

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

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@ public void SplayTree_Accuracy_Test()
8181
var nodeCount = 1000;
8282

8383
var rnd = new Random();
84-
var randomNumbers = Enumerable.Range(1, nodeCount)
84+
var sorted = Enumerable.Range(1, nodeCount).ToList();
85+
var randomNumbers = sorted
8586
.OrderBy(x => rnd.Next())
8687
.ToList();
8788

@@ -94,17 +95,34 @@ public void SplayTree_Accuracy_Test()
9495
Assert.IsTrue(tree.Count == i + 1);
9596
}
9697

98+
for (int i = 0; i < sorted.Count; i++)
99+
{
100+
Assert.AreEqual(sorted[i], tree.ElementAt(i));
101+
Assert.AreEqual(i, tree.IndexOf(sorted[i]));
102+
}
103+
97104
//shuffle again before deletion tests
98105
randomNumbers = Enumerable.Range(1, nodeCount)
99106
.OrderBy(x => rnd.Next())
100107
.ToList();
101108

102109
//IEnumerable test using linq
103110
Assert.AreEqual(tree.Count, tree.Count());
111+
Assert.AreEqual(tree.Count, tree.AsEnumerableDesc().Count());
104112

105113
for (int i = 0; i < nodeCount; i++)
106114
{
107-
tree.Delete(randomNumbers[i]);
115+
if (rnd.NextDouble() >= 0.5)
116+
{
117+
tree.Delete(randomNumbers[i]);
118+
}
119+
else
120+
{
121+
var index = tree.IndexOf(randomNumbers[i]);
122+
Assert.AreEqual(tree.ElementAt(index), randomNumbers[i]);
123+
tree.RemoveAt(index);
124+
}
125+
108126
tree.Root.VerifyCount();
109127
Assert.IsTrue(tree.Count == nodeCount - 1 - i);
110128
}
@@ -126,7 +144,7 @@ public void SplayTree_Stress_Test()
126144

127145
for (int i = 0; i < nodeCount; i++)
128146
{
129-
tree.Insert(randomNumbers[i]);
147+
tree.Insert(randomNumbers[i]);
130148
Assert.IsTrue(tree.Count == i + 1);
131149
}
132150

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

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@ public void TreapTree_Accuracy_Test()
8181
var nodeCount = 1000;
8282

8383
var rnd = new Random();
84-
var randomNumbers = Enumerable.Range(1, nodeCount)
84+
var sorted = Enumerable.Range(1, nodeCount).ToList();
85+
var randomNumbers = sorted
8586
.OrderBy(x => rnd.Next())
8687
.ToList();
8788

@@ -94,6 +95,11 @@ public void TreapTree_Accuracy_Test()
9495
Assert.IsTrue(tree.Count == i + 1);
9596
}
9697

98+
for (int i = 0; i < sorted.Count; i++)
99+
{
100+
Assert.AreEqual(sorted[i], tree.ElementAt(i));
101+
Assert.AreEqual(i, tree.IndexOf(sorted[i]));
102+
}
97103

98104
//shuffle again before deletion tests
99105
randomNumbers = Enumerable.Range(1, nodeCount)
@@ -102,10 +108,21 @@ public void TreapTree_Accuracy_Test()
102108

103109
//IEnumerable test using linq
104110
Assert.AreEqual(tree.Count, tree.Count());
111+
Assert.AreEqual(tree.Count, tree.AsEnumerableDesc().Count());
105112

106113
for (int i = 0; i < nodeCount; i++)
107114
{
108-
tree.Delete(randomNumbers[i]);
115+
if (rnd.NextDouble() >= 0.5)
116+
{
117+
tree.Delete(randomNumbers[i]);
118+
}
119+
else
120+
{
121+
var index = tree.IndexOf(randomNumbers[i]);
122+
Assert.AreEqual(tree.ElementAt(index), randomNumbers[i]);
123+
tree.RemoveAt(index);
124+
}
125+
109126
tree.Root.VerifyCount();
110127
Assert.IsTrue(tree.Count == nodeCount - 1 - i);
111128
}
@@ -127,7 +144,7 @@ public void TreapTree_Stress_Test()
127144

128145
for (int i = 0; i < nodeCount; i++)
129146
{
130-
tree.Insert(randomNumbers[i]);
147+
tree.Insert(randomNumbers[i]);
131148
Assert.IsTrue(tree.Count == i + 1);
132149
}
133150

0 commit comments

Comments
 (0)