Example #1
0
        /// <summary>
        /// Recursive add or update used in indexer.
        /// </summary>
        private AVLTreeMapNode <TKey, TValue> AddOrUpdate(AVLTreeMapNode <TKey, TValue> node, TKey key, TValue value, out bool updated)
        {
            updated = false;

            if (node == null)
            {
                return(new AVLTreeMapNode <TKey, TValue>(key, value));
            }

            int cmp = comparer.Compare(key, node.Key);

            if (cmp < 0)
            {
                node.Left = AddOrUpdate(node.Left, key, value, out updated);
            }
            else if (cmp > 0)
            {
                node.Right = AddOrUpdate(node.Right, key, value, out updated);
            }
            else
            {
                node.Value = value;
                updated    = true; // mark that value is updated
                return(node);
            }

            if (updated) // if only updated, no need to balance
            {
                return(node);
            }
            else
            {
                return(Balance(node));
            }
        }
Example #2
0
        /// <summary>
        /// Fixes the node height, calculating it from its children.
        /// </summary>
        private void FixHeight(AVLTreeMapNode <TKey, TValue> node)
        {
            var leftHeight  = NodeHeight(node.Left);
            var rightHeight = NodeHeight(node.Right);

            node.Height = (leftHeight > rightHeight ? leftHeight : rightHeight) + 1;
        }
Example #3
0
 /// <summary>
 /// Checks if balancing is needed and performs it.
 /// </summary>
 private AVLTreeMapNode <TKey, TValue> Balance(AVLTreeMapNode <TKey, TValue> node)
 {
     FixHeight(node);
     // if balance factor is -2 the left subtree is smaller than the right
     // so we need to perform a left rotation
     if (BalanceFactor(node) == -2)
     {
         if (BalanceFactor(node.Right) > 0)// Right Left Case if true, else Right Right Case
         {
             node.Right = RotateRight(node.Right);
         }
         return(RotateLeft(node));
     }
     // if balance factor is 2 the right subtree is smaller than the left
     // so we need to perform a right rotation
     if (BalanceFactor(node) == 2)
     {
         if (BalanceFactor(node.Left) < 0)// Left Right Case if true, else Left Left Case
         {
             node.Left = RotateLeft(node.Left);
         }
         return(RotateRight(node));
     }
     return(node);
 }
Example #4
0
 /// <summary>
 /// Finds and removes the min element of the given subtree.
 /// </summary>
 private AVLTreeMapNode <TKey, TValue> FindAndRemoveMin(AVLTreeMapNode <TKey, TValue> node, ref AVLTreeMapNode <TKey, TValue> min)
 {
     if (node.Left == null)
     {
         min = node;
         return(node.Right);
     }
     node.Left = FindAndRemoveMin(node.Left, ref min);
     return(Balance(node));
 }
Example #5
0
        /// <summary>
        /// Standard right rotation.
        /// </summary>
        private AVLTreeMapNode <TKey, TValue> RotateRight(AVLTreeMapNode <TKey, TValue> node)
        {
            AVLTreeMapNode <TKey, TValue> m = node.Left;

            node.Left = m.Right;
            m.Right   = node;
            FixHeight(node);
            FixHeight(m);
            return(m);
        }
Example #6
0
        /// <summary>
        /// Recursive removal with balancing on every step.
        /// </summary>
        private AVLTreeMapNode <TKey, TValue> Remove(AVLTreeMapNode <TKey, TValue> node, TKey key)
        {
            if (node == null)
            {
                return(node);
            }

            int cmp = comparer.Compare(key, node.Key);

            if (cmp < 0)
            {
                node.Left = Remove(node.Left, key);
            }
            else if (cmp > 0)
            {
                node.Right = Remove(node.Right, key);
            }
            else
            {
                Count--;
                AVLTreeMapNode <TKey, TValue> left  = node.Left;
                AVLTreeMapNode <TKey, TValue> right = node.Right;

                node.Invalidate();

                if (right == null)
                {
                    return(left);
                }

                AVLTreeMapNode <TKey, TValue> min = null;
                AVLTreeMapNode <TKey, TValue> rightSubtreeRoot = FindAndRemoveMin(right, ref min);
                min.Right = rightSubtreeRoot;
                min.Left  = left;

                return(Balance(min));
            }
            return(Balance(node));
        }
Example #7
0
        /// <summary>
        /// Recursive insertion with balancing on every step.
        /// </summary>
        private AVLTreeMapNode <TKey, TValue> Add(AVLTreeMapNode <TKey, TValue> node, TKey key, TValue value)
        {
            if (node == null)
            {
                return(new AVLTreeMapNode <TKey, TValue>(key, value));
            }

            int cmp = comparer.Compare(key, node.Key);

            if (cmp < 0)
            {
                node.Left = Add(node.Left, key, value);
            }
            else if (cmp > 0)
            {
                node.Right = Add(node.Right, key, value);
            }
            else
            {
                throw new ArgumentException("Tried to insert duplicate value!");
            }

            return(Balance(node));
        }
Example #8
0
 /// <summary>
 /// Gets the node height. Returns 0 if node is null.
 /// </summary>
 private int NodeHeight(AVLTreeMapNode <TKey, TValue> node)
 {
     return(node?.Height ?? 0);
 }
Example #9
0
 /// <summary>
 /// Calculates the balance factor.
 /// </summary>
 private int BalanceFactor(AVLTreeMapNode <TKey, TValue> node)
 {
     return(NodeHeight(node.Left) - NodeHeight(node.Right));
 }