@@ -14,24 +14,26 @@ public class BpTree<T> : IEnumerable<T> where T : IComparable
1414 internal BpTreeNode < T > Root ;
1515
1616 /// <summary>
17- ///Keep a reference of Bottom Left Node
18- ///For faster enumeration with IEnumerable implementation using Next pointer
17+ /// Keep a reference of Bottom Left Node
18+ /// for fast ascending/descending enumeration using Next pointer.
19+ /// See IEnumerable & IEnumerableDesc implementation at bottom.
1920 /// </summary>
2021 internal BpTreeNode < T > BottomLeftNode ;
22+ internal BpTreeNode < T > BottomRightNode ;
2123
2224 private readonly int maxKeysPerNode ;
2325 private readonly int minKeysPerNode ;
2426
2527 /// <summary>
26- /// Time complexity: O(log(n) ).
28+ /// Time complexity: O(1 ).
2729 /// </summary>
2830 public T Max
2931 {
3032 get
3133 {
3234 if ( Root == null ) return default ( T ) ;
3335
34- var maxNode = findMaxNode ( Root ) ;
36+ var maxNode = BottomRightNode ;
3537 return maxNode . Keys [ maxNode . KeyCount - 1 ] ;
3638 }
3739 }
@@ -50,7 +52,7 @@ public T Min
5052 }
5153 }
5254
53- public BpTree ( int maxKeysPerNode )
55+ public BpTree ( int maxKeysPerNode = 3 )
5456 {
5557 if ( maxKeysPerNode < 3 )
5658 {
@@ -122,6 +124,7 @@ public void Insert(T newValue)
122124 Root . KeyCount ++ ;
123125 Count ++ ;
124126 BottomLeftNode = Root ;
127+ BottomRightNode = Root ;
125128 return ;
126129 }
127130
@@ -204,6 +207,11 @@ private void insertAndSplit(ref BpTreeNode<T> node, T newValue,
204207 right . Next = node . Next ;
205208 node . Next . Prev = right ;
206209 }
210+ else
211+ {
212+ //bottom right most node
213+ BottomRightNode = right ;
214+ }
207215
208216 if ( node . Prev != null )
209217 {
@@ -212,7 +220,7 @@ private void insertAndSplit(ref BpTreeNode<T> node, T newValue,
212220 }
213221 else
214222 {
215- //left most bottom node
223+ //bottom left most node
216224 BottomLeftNode = left ;
217225 }
218226 }
@@ -559,7 +567,10 @@ private void sandwich(BpTreeNode<T> leftSibling, BpTreeNode<T> rightSibling, T d
559567 newNode . Next = rightSibling . Next ;
560568 rightSibling . Next . Prev = newNode ;
561569 }
562-
570+ else
571+ {
572+ BottomRightNode = newNode ;
573+ }
563574 }
564575
565576 var newIndex = 0 ;
@@ -912,6 +923,14 @@ private void removeAt<TS>(TS[] array, int index)
912923 Array . Copy ( array , index + 1 , array , index , array . Length - index - 1 ) ;
913924 }
914925
926+ /// <summary>
927+ /// Descending enumerable.
928+ /// </summary>
929+ public IEnumerable < T > AsEnumerableDesc ( )
930+ {
931+ return GetEnumeratorDesc ( ) . AsEnumerable ( ) ;
932+ }
933+
915934 //Implementation for the GetEnumerator method.
916935 IEnumerator IEnumerable . GetEnumerator ( )
917936 {
@@ -922,6 +941,11 @@ public IEnumerator<T> GetEnumerator()
922941 {
923942 return new BpTreeEnumerator < T > ( this ) ;
924943 }
944+
945+ public IEnumerator < T > GetEnumeratorDesc ( )
946+ {
947+ return new BpTreeEnumerator < T > ( this , false ) ;
948+ }
925949 }
926950
927951 internal class BpTreeNode < T > : BNode < T > where T : IComparable
@@ -970,14 +994,21 @@ internal override BNode<T>[] GetChildren()
970994
971995 internal class BpTreeEnumerator < T > : IEnumerator < T > where T : IComparable
972996 {
973- private BpTreeNode < T > bottomLeftNode ;
997+ private readonly bool asc ;
998+
999+ private BpTreeNode < T > startNode ;
9741000 private BpTreeNode < T > current ;
975- private int index = - 1 ;
9761001
977- internal BpTreeEnumerator ( BpTree < T > tree )
1002+ private int index ;
1003+
1004+ internal BpTreeEnumerator ( BpTree < T > tree , bool asc = true )
9781005 {
979- bottomLeftNode = tree . BottomLeftNode ;
980- current = bottomLeftNode ;
1006+ this . asc = asc ;
1007+
1008+ startNode = asc ? tree . BottomLeftNode : tree . BottomRightNode ;
1009+ current = startNode ;
1010+
1011+ index = asc ? - 1 : current . KeyCount ;
9811012 }
9821013
9831014 public bool MoveNext ( )
@@ -987,22 +1018,38 @@ public bool MoveNext()
9871018 return false ;
9881019 }
9891020
990- if ( index + 1 < current . KeyCount )
1021+ if ( asc )
9911022 {
992- index ++ ;
993- return true ;
1023+ if ( index + 1 < current . KeyCount )
1024+ {
1025+ index ++ ;
1026+ return true ;
1027+ }
1028+ }
1029+ else
1030+ {
1031+ if ( index - 1 >= 0 )
1032+ {
1033+ index -- ;
1034+ return true ;
1035+ }
9941036 }
9951037
996- current = current . Next ;
997- index = 0 ;
1038+ current = asc ? current . Next : current . Prev ;
1039+
1040+ var canMove = current != null && current . KeyCount > 0 ;
1041+ if ( canMove )
1042+ {
1043+ index = asc ? 0 : current . KeyCount - 1 ;
1044+ }
9981045
999- return current != null && current . KeyCount > 0 ;
1046+ return canMove ;
10001047 }
10011048
10021049 public void Reset ( )
10031050 {
1004- current = bottomLeftNode ;
1005- index = - 1 ;
1051+ current = startNode ;
1052+ index = asc ? - 1 : current . KeyCount ;
10061053 }
10071054
10081055 object IEnumerator . Current => Current ;
@@ -1018,8 +1065,7 @@ public T Current
10181065 public void Dispose ( )
10191066 {
10201067 current = null ;
1021- bottomLeftNode = null ;
1022- index = - 1 ;
1068+ startNode = null ;
10231069 }
10241070 }
10251071
0 commit comments