private IAvlNode CollectionToTree(IEnumerator enumerator, int height) { IAvlNode result; if (height == 0) { object data = null; if (enumerator.MoveNext()) { data = enumerator.Current; } result = new AvlNode( data, AvlNode.NullNode, AvlNode.NullNode); } else { IAvlNode leftChild, rightChild; object data = null; leftChild = CollectionToTree(enumerator, height - 1); if (enumerator.MoveNext()) { data = enumerator.Current; rightChild = CollectionToTree(enumerator, height - 1); } else { rightChild = GetSubTree(height - 1); } result = new AvlNode( data, leftChild, rightChild); } Debug.Assert(result.IsBalanced()); return(result); }
/// <summary> /// Initializes the ArrayList class. /// </summary> static ArrayList() { IAvlNode parent = AvlNode.NullNode; IAvlNode child = AvlNode.NullNode; // Create the tree pool. for(int i = 0; i < TreePoolHeight; i++) { parent = new AvlNode(null, child, child); child = parent; } TreePool = parent; // Postconditions. Debug.Assert(TreePool.Height == TreePoolHeight); }
/// <summary> /// Initializes the ArrayList class. /// </summary> static ArrayList() { IAvlNode parent = AvlNode.NullNode; IAvlNode child = AvlNode.NullNode; // Create the tree pool. for (int i = 0; i < TreePoolHeight; i++) { parent = new AvlNode(null, child, child); child = parent; } TreePool = parent; // Postconditions. Debug.Assert(TreePool.Height == TreePoolHeight); }
/// <summary> /// Removes the current node from the AVL tree. /// </summary> /// <returns> /// The node to in the tree to replace the current node. /// </returns> public IAvlNode Remove() { IAvlNode result; /* * Deal with the three cases for removing a node from a binary tree. */ // If the node has no right children. if (this.RightChild == AvlNode.NullNode) { // The replacement node is the node's left child. result = this.LeftChild; } // Else if the node's right child has no left children. else if (this.RightChild.LeftChild == AvlNode.NullNode) { // The replacement node is the node's right child. result = new AvlNode( this.RightChild.Data, this.LeftChild, this.RightChild.RightChild); } // Else the node's right child has left children. else { /* * Go to the node's right child and descend as far left as * possible. The node found at this point will replace the * node to be removed. */ IAvlNode replacement = AvlNode.NullNode; IAvlNode rightChild = RemoveReplacement(this.RightChild, ref replacement); // Create new node with the replacement node and the new // right child. result = new AvlNode( replacement.Data, this.LeftChild, rightChild); } return(result); }
// Recursive SetValue helper method. private IAvlNode SetValue(int index, object value, IAvlNode node) { // Preconditions. Debug.Assert(index >= 0 && index < node.Count); Debug.Assert(node != AvlNode.NullNode); IAvlNode result; int leftCount = node.LeftChild.Count; // If the node has been found. if (index == leftCount) { // Create new node with the new value. result = new AvlNode(value, node.LeftChild, node.RightChild); } // Else if the node is in the left tree. else if (index < leftCount) { // Create new node and move search to the left child. The new // node will reuse the right child subtree. result = new AvlNode( node.Data, SetValue(index, value, node.LeftChild), node.RightChild); } // Else if the node is in the right tree. else { // Create new node and move search to the right child. The new // node will reuse the left child subtree. result = new AvlNode( node.Data, node.LeftChild, SetValue(index - (leftCount + 1), value, node.RightChild)); } return(result); }
// Right - left double rotation. private IAvlNode DoRLRotation(IAvlNode node) { /* * An RL rotation looks like the following: * * Perform an LL rotation at B: * * A A * \ \ * B ---> C * / \ * C B * * Perform an RR rotation at A: * * A C * \ / \ * C ---> A B * \ * B */ IAvlNode a = new AvlNode( node.Data, node.LeftChild, DoLLRotation(node.RightChild)); IAvlNode c = DoRRRotation(a); // Postconditions. Debug.Assert(c.Data == node.RightChild.LeftChild.Data); Debug.Assert(c.LeftChild.Data == node.Data); Debug.Assert(c.RightChild.Data == node.RightChild.Data); return(c); }
// Remove the node with the specified key. private IAvlNode Remove(object key, IAvlNode node) { IAvlNode result; // The the key does not exist in the SortedList. if(node == AvlNode.NullNode) { // Result is null. result = node; } // Else the key has not yet been found. else { DictionaryEntry entry = (DictionaryEntry)node.Data; int compareResult = compareHandler(key, entry.Key); // If the specified key is less than the current key. if(compareResult < 0) { // Create node and continue searching to the left. result = new AvlNode( node.Data, Remove(key, node.LeftChild), node.RightChild); } // Else if the specified key is greater than the current key. else if(compareResult > 0) { // Create node and continue searching to the right. result = new AvlNode( node.Data, node.LeftChild, Remove(key, node.RightChild)); } // Else the node to remove has been found. else { // Remove node. result = node.Remove(); } } // If the node is out of balance. if(!result.IsBalanced()) { // Rebalance node. result = result.Balance(); } // Postconditions. Debug.Assert(result.IsBalanced()); return result; }
private IAvlNode CollectionToTree(IEnumerator enumerator, int height) { IAvlNode result; if(height == 0) { object data = null; if(enumerator.MoveNext()) { data = enumerator.Current; } result = new AvlNode( data, AvlNode.NullNode, AvlNode.NullNode); } else { IAvlNode leftChild, rightChild; object data = null; leftChild = CollectionToTree(enumerator, height - 1); if(enumerator.MoveNext()) { data = enumerator.Current; rightChild = CollectionToTree(enumerator, height - 1); } else { rightChild = GetSubTree(height - 1); } result = new AvlNode( data, leftChild, rightChild); } Debug.Assert(result.IsBalanced()); return result; }
// Recursive Insert helper method. private IAvlNode Insert(int index, object value, IAvlNode node) { // Preconditions. Debug.Assert(index >= 0 && index <= Count); Debug.Assert(node != null); /* * The insertion algorithm searches for the correct place to add a * new node at the bottom of the tree using the specified index. */ IAvlNode result; // If the bottom of the tree has not yet been reached. if (node != AvlNode.NullNode) { int leftCount = node.LeftChild.Count; // If we need to descend to the left. if (index <= leftCount) { // Create new node and move search to the left child. The // new node will reuse the right child subtree. result = new AvlNode( node.Data, Insert(index, value, node.LeftChild), node.RightChild); } // Else we need to descend to the right. else { // Create new node and move search to the right child. The // new node will reuse the left child subtree. result = new AvlNode( node.Data, node.LeftChild, Insert(index - (leftCount + 1), value, node.RightChild)); } } // Else the bottom of the tree has been reached. else { // Create new node at the specified index. result = new AvlNode(value, AvlNode.NullNode, AvlNode.NullNode); } /* * This check isn't necessary if a node has already been rebalanced * after an insertion. AVL tree insertions never require more than * one rebalancing. However, it's easier to go ahead and check at * this point since we're using recursion. This may need optimizing * in the future. */ // If the node is not balanced. if (!result.IsBalanced()) { // Rebalance node. result = result.Balance(); } // Postconditions. Debug.Assert(result.IsBalanced()); return(result); }
// Left - left single rotation. private IAvlNode DoLLRotation(IAvlNode node) { /* * An LL rotation looks like the following: * * A B * / / \ * B ---> C A * / * C */ // Create right child of the new root. IAvlNode a = new AvlNode( node.Data, node.LeftChild.RightChild, node.RightChild); IAvlNode b = new AvlNode( node.LeftChild.Data, node.LeftChild.LeftChild, a); // Postconditions. Debug.Assert(b.Data == node.LeftChild.Data); Debug.Assert(b.LeftChild == node.LeftChild.LeftChild); Debug.Assert(b.RightChild.Data == node.Data); return b; }
// Enlarges the tree used by the ArrayList. private IAvlNode EnlargeTree() { // Preconditions. Debug.Assert(root.Height <= TreePool.Height); // Create new root for the enlarged tree. IAvlNode result = new AvlNode(null, root, GetSubTree(root.Height)); // Postconditions. Debug.Assert(result.BalanceFactor == 0); Debug.Assert(result.Height == root.Height + 1); return result; }
/// <summary> /// Removes the current node from the AVL tree. /// </summary> /// <returns> /// The node to in the tree to replace the current node. /// </returns> public IAvlNode Remove() { IAvlNode result; /* * Deal with the three cases for removing a node from a binary tree. */ // If the node has no right children. if(this.RightChild == AvlNode.NullNode) { // The replacement node is the node's left child. result = this.LeftChild; } // Else if the node's right child has no left children. else if(this.RightChild.LeftChild == AvlNode.NullNode) { // The replacement node is the node's right child. result = new AvlNode( this.RightChild.Data, this.LeftChild, this.RightChild.RightChild); } // Else the node's right child has left children. else { /* * Go to the node's right child and descend as far left as * possible. The node found at this point will replace the * node to be removed. */ IAvlNode replacement = AvlNode.NullNode; IAvlNode rightChild = RemoveReplacement(this.RightChild, ref replacement); // Create new node with the replacement node and the new // right child. result = new AvlNode( replacement.Data, this.LeftChild, rightChild); } return result; }
// Finds and removes replacement node for deletion (third case). private IAvlNode RemoveReplacement(IAvlNode node, ref IAvlNode replacement) { IAvlNode newNode; // If the bottom of the left tree has been found. if(node.LeftChild == AvlNode.NullNode) { // The replacement node is the node found at this point. replacement = node; // Get the node's right child. This will be needed as we // ascend back up the tree. newNode = node.RightChild; } // Else the bottom of the left tree has not been found. else { // Create new node and continue descending down the left tree. newNode = new AvlNode(node.Data, RemoveReplacement(node.LeftChild, ref replacement), node.RightChild); // If the node is out of balance. if(!newNode.IsBalanced()) { // Rebalance the node. newNode = newNode.Balance(); } } // Postconditions. Debug.Assert(newNode.IsBalanced()); return newNode; }
// Right - left double rotation. private IAvlNode DoRLRotation(IAvlNode node) { /* * An RL rotation looks like the following: * * Perform an LL rotation at B: * * A A * \ \ * B ---> C * / \ * C B * * Perform an RR rotation at A: * * A C * \ / \ * C ---> A B * \ * B */ IAvlNode a = new AvlNode( node.Data, node.LeftChild, DoLLRotation(node.RightChild)); IAvlNode c = DoRRRotation(a); // Postconditions. Debug.Assert(c.Data == node.RightChild.LeftChild.Data); Debug.Assert(c.LeftChild.Data == node.Data); Debug.Assert(c.RightChild.Data == node.RightChild.Data); return c; }
// Recursive SetValue helper method. private IAvlNode SetValue(int index, object value, IAvlNode node) { // Preconditions. Debug.Assert(index >= 0 && index < node.Count); Debug.Assert(node != AvlNode.NullNode); IAvlNode result; int leftCount = node.LeftChild.Count; // If the node has been found. if(index == leftCount) { // Create new node with the new value. result = new AvlNode(value, node.LeftChild, node.RightChild); } // Else if the node is in the left tree. else if(index < leftCount) { // Create new node and move search to the left child. The new // node will reuse the right child subtree. result = new AvlNode( node.Data, SetValue(index, value, node.LeftChild), node.RightChild); } // Else if the node is in the right tree. else { // Create new node and move search to the right child. The new // node will reuse the left child subtree. result = new AvlNode( node.Data, node.LeftChild, SetValue(index - (leftCount + 1), value, node.RightChild)); } return result; }
// Adds key/value pair to the internal AVL tree. private IAvlNode Add(object key, object value, IAvlNode node) { IAvlNode result; // If the bottom of the tree has been reached. if(node == AvlNode.NullNode) { // Create new node representing the new key/value pair. result = new AvlNode( new DictionaryEntry(key, value), AvlNode.NullNode, AvlNode.NullNode); } // Else the bottom of the tree has not been reached. else { DictionaryEntry entry = (DictionaryEntry)node.Data; int compareResult = compareHandler(key, entry.Key); // If the specified key is less than the current key. if(compareResult < 0) { // Create new node and continue searching to the left. result = new AvlNode( node.Data, Add(key, value, node.LeftChild), node.RightChild); } // Else the specified key is greater than the current key. else if(compareResult > 0) { // Create new node and continue searching to the right. result = new AvlNode( node.Data, node.LeftChild, Add(key, value, node.RightChild)); } // Else the specified key is equal to the current key. else { // Throw exception. Duplicate keys are not allowed. throw new ArgumentException( "Item is already in the collection."); } } // If the current node is not balanced. if(!result.IsBalanced()) { // Balance node. result = result.Balance(); } return result; }
// Recursive Insert helper method. private IAvlNode Insert(int index, object value, IAvlNode node) { // Preconditions. Debug.Assert(index >= 0 && index <= Count); Debug.Assert(node != null); /* * The insertion algorithm searches for the correct place to add a * new node at the bottom of the tree using the specified index. */ IAvlNode result; // If the bottom of the tree has not yet been reached. if(node != AvlNode.NullNode) { int leftCount = node.LeftChild.Count; // If we need to descend to the left. if(index <= leftCount) { // Create new node and move search to the left child. The // new node will reuse the right child subtree. result = new AvlNode( node.Data, Insert(index, value, node.LeftChild), node.RightChild); } // Else we need to descend to the right. else { // Create new node and move search to the right child. The // new node will reuse the left child subtree. result = new AvlNode( node.Data, node.LeftChild, Insert(index - (leftCount + 1), value, node.RightChild)); } } // Else the bottom of the tree has been reached. else { // Create new node at the specified index. result = new AvlNode(value, AvlNode.NullNode, AvlNode.NullNode); } /* * This check isn't necessary if a node has already been rebalanced * after an insertion. AVL tree insertions never require more than * one rebalancing. However, it's easier to go ahead and check at * this point since we're using recursion. This may need optimizing * in the future. */ // If the node is not balanced. if(!result.IsBalanced()) { // Rebalance node. result = result.Balance(); } // Postconditions. Debug.Assert(result.IsBalanced()); return result; }
// Recursive RemoveAt helper method. private IAvlNode RemoveAt(int index, IAvlNode node) { // Preconditions. Debug.Assert(index >= 0 && index < Count); Debug.Assert(node != AvlNode.NullNode); IAvlNode newNode; int leftCount = node.LeftChild.Count; // If the node has been found. if(index == leftCount) { newNode = node.Remove(); } // Else if the node is in the left tree. else if(index < leftCount) { // Create new node and move search to the left child. The new // node will reuse the right child subtree. newNode = new AvlNode( node.Data, RemoveAt(index, node.LeftChild), node.RightChild); } // Else if the node is in the right tree. else { // Create new node and move search to the right child. The new // node will reuse the left child subtree. newNode = new AvlNode( node.Data, node.LeftChild, RemoveAt(index - (leftCount + 1), node.RightChild)); } // If the node is out of balance. if(!newNode.IsBalanced()) { // Rebalance node. newNode = newNode.Balance(); } // Postconditions. Debug.Assert(newNode.IsBalanced()); return newNode; }