public ITwoThree <T> Insert(T item, IComparer <T> comparer, out ITwoThree <T> splitLeft, out ITwoThree <T> splitRight, out T splitValue) { splitLeft = splitRight = Instance; splitValue = item; return(null); }
// Constructors public TwoNode(T value, ITwoThree <T> left, ITwoThree <T> right) { Value = value; Left = left; Right = right; }
public ITwoThree <T> Insert(T item, IComparer <T> comparer, out ITwoThree <T> splitLeft, out ITwoThree <T> splitRight, out T splitValue) { var side = GetSide(item, comparer); if (side == Side.Same) { splitLeft = null; splitRight = null; splitValue = default(T); return(this); } var child = GetChild(side); var node = child.Insert(item, comparer, out splitLeft, out splitRight, out splitValue); if (node == null) { // Child node split. return(side == Side.Left ? new ThreeNode <T>(splitValue, Value, splitLeft, splitRight, Right) : new ThreeNode <T>(Value, splitValue, Left, splitLeft, splitRight)); } // Single node was splitValue. if (node == child) { return(this); } return(side == Side.Left ? new TwoNode <T>(Value, node, Right) : new TwoNode <T>(Value, Left, node)); }
public static ITwoThree <T> Remove <T>(this ITwoThree <T> root, T item, IComparer <T> comparer = null) { comparer = comparer ?? Comparer <T> .Default; bool removed; return(root.Remove(item, comparer, out removed)); }
private void AssertValid <T>(ITwoThree <T> tree) { var values = tree.GetValues().ToArray(); Assert.True(tree.IsBalanced()); CollectionAssert.IsOrdered(values); CollectionAssert.AllItemsAreUnique(values); }
public static ITwoThree <T> Insert <T>(this ITwoThree <T> root, T item, IComparer <T> comparer = null) { comparer = comparer ?? Comparer <T> .Default; T propagated; ITwoThree <T> left, right; var node = root.Insert(item, comparer, out left, out right, out propagated); return(node ?? new TwoNode <T>(propagated, left, right)); }
public ImmutableSortedDictionary(IComparer <TKey> keyComparer) { if (keyComparer == null) { throw new ArgumentNullException(nameof(keyComparer)); } _root = EmptyTwoThree <KeyValuePair <TKey, TValue> > .Instance; _comparer = new KeyComparer <TKey, TValue>(keyComparer); }
// Constructors public ThreeNode(T first, T second, ITwoThree <T> left, ITwoThree <T> middle, ITwoThree <T> right) { First = first; Second = second; Left = left; Middle = middle; Right = right; Debug.Assert(left.IsNullOrEmpty() && middle.IsNullOrEmpty() && right.IsNullOrEmpty() || !left.IsNullOrEmpty() && !middle.IsNullOrEmpty() && !right.IsNullOrEmpty()); }
public ITwoThree <T> Insert(T item, IComparer <T> comparer, out ITwoThree <T> splitLeft, out ITwoThree <T> splitRight, out T splitValue) { // Default split values. splitLeft = splitRight = null; splitValue = default(T); // Get side to insert node. var side = GetSide(item, comparer); // Values are equal, no need to change tree. if (IsSame(side)) { return(this); } // Insert value into proper node. T pv; ITwoThree <T> pl, pr; var child = GetChild(side); var node = child.Insert(item, comparer, out pl, out pr, out pv); // Insert propagated single node. if (node != null) { return(node == child ? this : NewChangedNode(node, side)); } // Insert propagated two nodes and value, meaning it split. // Sinde this is 3-node, we are at full capacity and need to split too. switch (side) { case Side.Left: splitLeft = new TwoNode <T>(pv, pl, pr); splitRight = new TwoNode <T>(Second, Middle, Right); splitValue = First; break; case Side.Middle: splitLeft = new TwoNode <T>(First, Left, pl); splitRight = new TwoNode <T>(Second, pr, Right); splitValue = pv; break; case Side.Right: splitLeft = new TwoNode <T>(First, Left, Middle); splitRight = new TwoNode <T>(pv, pl, pr); splitValue = Second; break; } return(null); }
private ITwoThree <T> RedistributeCons(T value, ITwoThree <T> changed, Side side, out bool removed) { switch (side) { case Side.SameFirst: return(Redistribute(value, Second, Left, changed, Right, Side.Middle, out removed)); case Side.SameSecond: return(Redistribute(First, value, Left, Middle, changed, Side.Right, out removed)); default: throw new ArgumentOutOfRangeException(nameof(side)); } }
private ITwoThree <T> NewChangedWithConsequent(T value, ITwoThree <T> node, Side side) { switch (side) { case Side.SameFirst: return(new ThreeNode <T>(value, Second, Left, node, Right)); case Side.SameSecond: return(new ThreeNode <T>(First, value, Left, Middle, node)); default: throw new ArgumentOutOfRangeException(nameof(side)); } }
private ITwoThree <T> RedistributeOrMerge(T value, ITwoThree <T> left, ITwoThree <T> right, Side removedSide, out bool removed) { removed = false; if (removedSide == Side.Right) { if (left is ThreeNode <T> ) { // Right redistribute case. var red = (ThreeNode <T>)left; var l = new TwoNode <T>(red.First, red.Left, red.Middle); var r = new TwoNode <T>(value, red.Right, right); return(new TwoNode <T>(red.Second, l, r)); } // Right merge case. var m = (TwoNode <T>)left; removed = true; return(new ThreeNode <T>(m.Value, value, m.Left, m.Right, right)); } if (removedSide == Side.Left) { if (right is ThreeNode <T> ) { // Left redistribute case. var led = (ThreeNode <T>)right; var l = new TwoNode <T>(value, left, led.Left); var r = new TwoNode <T>(led.Second, led.Middle, led.Right); return(new TwoNode <T>(led.First, l, r)); } // Left merge case. var m = (TwoNode <T>)right; removed = true; return(new ThreeNode <T>(value, m.Value, left, m.Left, m.Right)); } throw new InvalidOperationException(); }
private ITwoThree <T> RedistributeFrom(ITwoThree <T> changed, Side side, out bool removed) { switch (side) { case Side.Left: return(Redistribute(First, Second, changed, Middle, Right, side, out removed)); case Side.Middle: return(Redistribute(First, Second, Left, changed, Right, side, out removed)); case Side.Right: return(Redistribute(First, Second, Left, Middle, changed, side, out removed)); default: throw new ArgumentOutOfRangeException(nameof(side)); } }
private ITwoThree <T> NewChangedNode(ITwoThree <T> node, Side side) { switch (side) { case Side.Left: return(new ThreeNode <T>(First, Second, node, Middle, Right)); case Side.Middle: return(new ThreeNode <T>(First, Second, Left, node, Right)); case Side.Right: return(new ThreeNode <T>(First, Second, Left, Middle, node)); default: throw new InvalidOperationException(); } }
private static ITwoThree <T> RedistributeRight(T first, T second, ITwoThree <T> left, ITwoThree <T> middle, ITwoThree <T> right) { // Case A if (left is TwoNode <T> && middle is TwoNode <T> ) { var sm = (TwoNode <T>)middle; var l = left; var r = new ThreeNode <T>(sm.Value, second, sm.Left, sm.Right, right); return(new TwoNode <T>(first, l, r)); } // Case B if (middle is ThreeNode <T> ) { var sm = (ThreeNode <T>)middle; var l = left; var m = new TwoNode <T>(sm.First, sm.Left, sm.Middle); var r = new TwoNode <T>(second, sm.Right, right); return(new ThreeNode <T>(first, sm.Second, l, m, r)); } // Case C if (left is ThreeNode <T> && middle is TwoNode <T> ) { var sl = (ThreeNode <T>)left; var sm = (TwoNode <T>)middle; var l = new TwoNode <T>(sl.First, sl.Left, sl.Middle); var m = new TwoNode <T>(first, sl.Right, sm.Left); var r = new TwoNode <T>(second, sm.Right, right); return(new ThreeNode <T>(sl.Second, sm.Value, l, m, r)); } throw new InvalidOperationException(); }
private static ITwoThree <T> RedistributeMiddle(T first, T second, ITwoThree <T> left, ITwoThree <T> middle, ITwoThree <T> right) { // Case A if (left is TwoNode <T> && right is TwoNode <T> ) { var sl = (TwoNode <T>)left; var l = new ThreeNode <T>(sl.Value, first, sl.Left, sl.Right, middle); var r = right; return(new TwoNode <T>(second, l, r)); } // Case B if (right is ThreeNode <T> ) { var sr = (ThreeNode <T>)right; var l = left; var m = new TwoNode <T>(second, middle, sr.Left); var r = new TwoNode <T>(sr.Second, sr.Middle, sr.Right); return(new ThreeNode <T>(first, sr.First, l, m, r)); } // Case C if (left is ThreeNode <T> && right is TwoNode <T> ) { var sl = (ThreeNode <T>)left; var l = new TwoNode <T>(sl.First, sl.Left, sl.Middle); var m = new TwoNode <T>(first, sl.Right, middle); var r = right; return(new ThreeNode <T>(sl.Second, second, l, m, r)); } throw new InvalidOperationException(); }
private static ITwoThree <T> Redistribute(T first, T second, ITwoThree <T> left, ITwoThree <T> middle, ITwoThree <T> right, Side side, out bool removed) { removed = false; if (side == Side.Left) { return(RedistributeLeft(first, second, left, middle, right)); } if (side == Side.Middle) { return(RedistributeMiddle(first, second, left, middle, right)); } if (side == Side.Right) { return(RedistributeRight(first, second, left, middle, right)); } throw new ArgumentOutOfRangeException(nameof(side)); }
public static bool IsNullOrEmpty <T>(this ITwoThree <T> node) { return(node == null || node is EmptyTwoThree <T>); }
// Constructors public ImmutableSortedDictionary() { _root = EmptyTwoThree <KeyValuePair <TKey, TValue> > .Instance; _comparer = new KeyComparer <TKey, TValue>(); }
private ImmutableSortedDictionary(ITwoThree <KeyValuePair <TKey, TValue> > root, KeyComparer <TKey, TValue> comparer) { _root = root; _comparer = comparer; }
// Constructors public ImmutableSortedSet() { _root = EmptyTwoThree <T> .Instance; _comparer = Comparer <T> .Default; }
public static bool IsBalanced <T>(this ITwoThree <T> node) { int depth; return(node.IsBalanced(out depth)); }
private ImmutableSortedSet(ITwoThree <T> root, IComparer <T> comparer) { _root = root; _comparer = comparer; }