private int _indexOf(AvlTreeNode <T> node) { if (node == null) { throw new ArgumentNullException(nameof(node)); } // the index of a node is actually that number of nodes that are "before" it. That includes // left children, and left siblings, including ancestors that the node is "right child" of. var count = _leftSize(node); var cur = node; while (cur.Parent != null) { if (cur.Parent.Right == cur) // if cur is the right child of the parent { count = count + _leftSize(cur.Parent) + 1; // count all the left descendants of the parent, and the parent itself } cur = cur.Parent; } return(count); }
private void _attachToParentEdge(AvlTreeNode <T> node, AvlTreeEdge <T> edge) { Debug.Assert(edge.IsChildOrRoot); // if node != null, node.parent should be free Debug.Assert((node == null) || (node.Parent == null)); // if edge is child then the target should be free; Debug.Assert((edge.IsRoot) || (edge.Target() == null)); if (edge.IsRoot) { _setAsRoot(node); } else if (edge.Direction == AvlTreeNodeDirection.Left) { edge.Source.Left = node; if (node != null) { node.Parent = edge.Source; } } else { edge.Source.Right = node; if (node != null) { node.Parent = edge.Source; } } }
public static AvlTreeEdge <T> FindFree <T>(this AvlTreeNode <T> source, Func <AvlTreeNode <T>, AvlTreeEdge <T> > selector) { if (source == null) { return(AvlTreeEdge <T> .Root); } var current = source; AvlTreeEdge <T> res = null; while (res == null) { var edge = selector(current); var next = edge.Target(); if (next == null) { res = edge; } current = next; } return(res); }
private AvlTreeNode <T> _doBalance(AvlTreeNode <T> node) { int bal = node.Balance; Debug.Assert(Math.Abs(bal) <= 2); AvlTreeNode <T> res = node; if (bal == -2) { Debug.Assert(Math.Abs(node.Left.Balance) <= 1); if (node.Left.Balance == 1) { _rotateLeft(node.Left); } res = _rotateRight(node); } else if (bal == 2) { Debug.Assert(Math.Abs(node.Right.Balance) <= 1); if (node.Right.Balance == -1) { node.Right = _rotateRight(node.Right); } res = _rotateLeft(node); } return(res); }
/* Parent Parent * |- |+ * B A * -/ \ / \+ * A BL -> AL B * / \- +/ \ * AL C C BR * * - marks connections that are dettached * + marks connections that are created */ private AvlTreeNode <T> _rotateRight(AvlTreeNode <T> b) { AvlTreeNode <T> a = b.Left; AvlTreeNode <T> parent = b.Parent; // may be null if B was root AvlTreeNode <T> c = a.Right; // may be null var direction = b.Direction; Debug.Assert(a != null); // a.Left remains so no need to change this // b.Right remains so no need to change this _dettachFromParent(b); // b from parent _dettachFromParent(a); // a from b _dettachFromParent(c); // c from a _attachToParentEdge(c, b.EdgeLeft()); _attachToParentEdge(b, a.EdgeRight()); _attachToParentEdge(a, parent.EdgeTo(direction)); _recalc(b); _recalc(a); return(a); }
internal AvlTreeNode <T> InternalPredecessor(AvlTreeNode <T> node) { Debug.Assert(node != null); // 3 cases: // case 1 - there is a left subtree, in that case, the predecessor is the last in the left sub tree. // case 2 - there is no left subtree, but there is a parent - the predecessor is the first parent "on the left" - so it's child is a right child // case 3 - no parent, or we keep clibing up parents where we are the "child on the left" - there is no predecessor // case 1 if (node.Left != null) { return(InternalLastInSubtree(node.Left)); } var cur = node; while (cur.Parent != null) { // case 2 // if we are the right child, so the parent is on our left - this is the predecessor if (cur.Direction == AvlTreeNodeDirection.Right) { return(cur.Parent); } // else - keep climbing up cur = cur.Parent; } // case 3 - no more parents - no predecessor return(null); }
private AvlTreeNode <T> rec_createRangeSubtree(T[] items, int start, int end) { if (start > end) { return(null); } var mid = (start + end) / 2; var item = items[mid]; var node = new AvlTreeNode <T>(item); var left = rec_createRangeSubtree(items, start, mid - 1); var right = rec_createRangeSubtree(items, mid + 1, end); if (left != null) { _attachToParentEdge(left, node.EdgeLeft()); } if (right != null) { _attachToParentEdge(right, node.EdgeRight()); } _recalc(node); return(node); }
public static string ToVisualString <T>(this AvlTreeNode <T> source, string textFormat = "{0}", int spacing = 2, int topMargin = 1, int leftMargin = 1) { var console = new StringConsole(); source.PrintToConsole(console, textFormat, spacing, topMargin, leftMargin); return(console.ToString()); }
public AvlTreeNode <T> PredecessorOf(AvlTreeNode <T> node) { if (node == null) { throw new ArgumentNullException(nameof(node)); } return(InternalPredecessor(node)); }
public AvlTreeNode <T> LastInSubtree(AvlTreeNode <T> node) { if (node == null) { throw new ArgumentNullException(nameof(node)); } return(InternalLastInSubtree(node)); }
public static AvlTreeEdge <T> For(AvlTreeNode <T> source, AvlTreeNodeDirection direction) { if (source == null) { return(Root); } return(new AvlTreeEdge <T>(source, direction)); }
// Needs to be called every time the left or right subtree is changed. // Assumes the left and right subtrees have the correct values computed already. private void _recalc(AvlTreeNode <T> node) { Debug.Assert(node != null); node.Height = Math.Max(node.Left?.Height ?? 0, node.Right?.Height ?? 0) + 1; node.Size = (node.Left?.Size ?? 0) + (node.Right?.Size ?? 0) + 1; Debug.Assert((node.Height >= 1) && (node.Size >= 1)); }
private AvlTreeNode <T> _add(AvlTreeNode <T> node) { var item = node.Item; var edge = this.FindFree(n => _comparer.Compare(item, n.Item) > 0 ? n.EdgeRight() : n.EdgeLeft()); return(InternalInsertNode(edge, node)); }
public AvlTreeNode <T> AddBefore(AvlTreeNode <T> anchor, T item) { if (anchor == null) { throw new ArgumentNullException(nameof(anchor)); } var indexOfAnchor = anchor.LeftSize; // index of anchor relative to it's own subtree == the number of items at its left return(_insertInRelativeIndex(anchor, indexOfAnchor, item)); }
internal AvlTreeNode <T> InternalLastInSubtree(AvlTreeNode <T> node) { Debug.Assert(node != null); var cur = node; while (cur.Right != null) { cur = cur.Right; } return(cur); }
private void _unsetRoot(AvlTreeNode <T> node) { Debug.Assert(Root == node); Debug.Assert((node == null) || (node.Parent == null)); Debug.Assert((node == null) || (node._tree == this)); Root = null; if (node != null) { node._tree = null; } }
private void _setAsRoot(AvlTreeNode <T> node) { Debug.Assert(Root == null); Debug.Assert(node.Parent == null); Debug.Assert(node._tree == null); Root = node; if (node != null) { node._tree = this; } }
private void _rebalanceAfterChange(AvlTreeNode <T> start) { while (start != null) { var direction = start.Direction; _recalc(start); var parent = start.Parent; var balanced = _doBalance(start); start = parent; } }
private void rec_checkStructure(AvlTreeNode <T> node, ISet <AvlTreeNode <T> > visitedNodes) { if (node == null) { return; } if (!visitedNodes.Add(node)) { throw new SystemException("AVL tree structure violated: Not a tree"); } CheckStructureOfNode(node); rec_checkStructure(node.Left, visitedNodes); rec_checkStructure(node.Right, visitedNodes); if ((node.Left != null) && (node.Left.Parent != node)) { throw new SystemException("AVL tree structure violated: node.Left.Parent != node"); } if ((node.Right != null) && (node.Right.Parent != node)) { throw new SystemException("AVL tree structure violated: node.Right.Parent != node"); } if (node.Height != Math.Max((node.Left?.Height ?? 0), (node.Right?.Height ?? 0)) + 1) { throw new SystemException("AVL tree structure violated: Incorrect cached height"); } if (node.Size != (node.Left?.Size ?? 0) + (node.Right?.Size ?? 0) + 1) { throw new SystemException("AVL tree structure violated: Incorrect cached size"); } if (Math.Abs(node.Balance) > 1) { throw new SystemException("AVL tree structure violated: Height imbalance"); } }
protected override void CheckStructureOfNode(AvlTreeNode <T> node) { if (node.Left != null) { var comp = _comparer.Compare(node.Item, node.Left.Item); if (comp < 0) { throw new SystemException("Sorted tree, node item smaller than its left child item"); } } if (node.Right != null) { var comp = _comparer.Compare(node.Item, node.Right.Item); if (comp > 0) { throw new SystemException("Sorted tree, node item larger than its right child item"); } } }
private IEnumerable <AvlTreeNode <T> > _enumerate(AvlTreeNode <T> node) { var res = Enumerable.Empty <AvlTreeNode <T> >(); if (node == null) { return(res); } if (node.Left != null) { res = res.Concat(_enumerate(node.Left)); } res = res.Concat(node); if (node.Right != null) { res = res.Concat(_enumerate(node.Right)); } return(res); }
private AvlTreeNode <T> _insertInRelativeIndex(AvlTreeNode <T> anchor, int index, T item) { Debug.Assert(index >= 0); Debug.Assert((anchor != null) || (index == 0)); // if anchor is null, index must be 0 Debug.Assert((anchor == null) || (index <= anchor.Size)); // if anchor is not null, index must be less than or queal to // the size of the subtree var newNode = new AvlTreeNode <T>(item); if (anchor == null) { return(InternalInsertNode(AvlTreeEdge <T> .Root, newNode)); } var edge = anchor.FindFree(index, (node, idx) => { int leftSize = node.LeftSize; if (idx <= leftSize) { return(node.EdgeLeft(), idx); }
private AvlTreeNode <T> rec_getNodeAt(AvlTreeNode <T> node, int index) { var nodeSize = _size(node); if ((index < 0) || (index >= nodeSize)) { throw new ArgumentOutOfRangeException(nameof(index)); } int leftSize = _leftSize(node); if (index < leftSize) { return(rec_getNodeAt(node.Left, index)); } if (index > leftSize) { return(rec_getNodeAt(node.Right, index - leftSize - 1)); } return(node); }
internal AvlTreeNode <T> InternalInsertNode(AvlTreeEdge <T> edge, AvlTreeNode <T> newNode) { Debug.Assert(edge.IsChildOrRoot); if (Count == int.MaxValue) { throw new InvalidOperationException("Maximum size reached"); } _version++; // newnode should be dettached from the tree Debug.Assert(newNode != null); Debug.Assert(newNode.Parent == null); Debug.Assert(newNode.Left == null); Debug.Assert(newNode.Right == null); Debug.Assert(newNode._tree == null); _attachToParentEdge(newNode, edge); _rebalanceAfterChange(edge.Source); return(newNode); }
private void _dettachFromParent(AvlTreeNode <T> node) { if (node == null) { return; } if (node.Parent == null) { _unsetRoot(node); } else if (node.Parent.Left == node) { node.Parent.Left = null; node.Parent = null; } else { node.Parent.Right = null; node.Parent = null; } }
internal override void OnItemChanged(AvlTreeNode <T> node) { // remove and reinsert the item so it ends up in the right place InternalRemoveNode(node); _add(node); }
private AvlTreeEdge(AvlTreeNode <T> source, AvlTreeNodeDirection direction) { Source = source; Direction = direction; }
public static AvlTreeEdge <T> EdgeSelf <T>(this AvlTreeNode <T> source) { return(source.EdgeTo(AvlTreeNodeDirection.None)); }
public static AvlTreeEdge <T> EdgeParent <T>(this AvlTreeNode <T> source) { return(source.EdgeTo(AvlTreeNodeDirection.Parent)); }
public static AvlTreeEdge <T> EdgeTo <T>(this AvlTreeNode <T> source, AvlTreeNodeDirection direction) { return(For(source, direction)); }