Ejemplo n.º 1
0
        /// <inheritdoc cref="IHeap{TKey,TValue}.Remove"/>
        public override TValue Remove(PairingHeapNode <TKey, TValue> node)
        {
            if (node == null)
            {
                throw new ArgumentNullException(nameof(node));
            }

            // Remove the node from its list of siblings. Merge all its children to form
            // a new tree and merge that tree with the root.

            var item = node.Value;

            if (node == this.Root)
            {
                // Simplified case when we remove the root
                this.Root = this.MergePairwisely(node.Child);
            }
            else
            {
                // The node is somewhere in the middle of the tree, so before we handle
                // the child of the node, we also need to fix the list of siblings.

                node.RemoveFromListOfSiblings();

                // The only part left is the child of the node. As stated previously,
                // we will simply merge it with the entire heap.

                this.Root = this.Merge(this.Root, this.MergePairwisely(node.Child));
            }

            --this.count;
            return(item);
        }
Ejemplo n.º 2
0
        /// <inheritdoc cref="IHeap{TKey,TValue}.Add"/>
        public override PairingHeapNode <TKey, TValue> Add(TKey key, TValue value)
        {
            // Create a one-node tree for the specified item and merge it with this heap.
            var tree = new PairingHeapNode <TKey, TValue>(key, value);

            this.Root = this.Merge(this.Root, tree);
            ++this.count;

            return(tree);
        }
Ejemplo n.º 3
0
        /// <inheritdoc cref="IHeap{TKey,TValue}.Merge"/>
        public override void Merge(PairingHeap <TKey, TValue> other)
        {
            if (other == null)
            {
                throw new ArgumentNullException(nameof(other));
            }

            this.count += other.count;
            this.Root   = this.Merge(this.Root, other.Root);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Performs a two-pass pairing over a list of siblings to form a single tree.
        /// </summary>
        /// <param name="node">The leftmost node (head) of the list to combine.</param>
        private PairingHeapNode <TKey, TValue> MergePairwisely(PairingHeapNode <TKey, TValue> node)
        {
            if (node == null)
            {
                return(null);
            }

            PairingHeapNode <TKey, TValue> result, tail = null, next = node;

            // The first pass is based on iterating left to right, merging trees pairwisely.
            // We take two trees from the list, replace them by the result of merging, and
            // consider two next trees. Note that after a pair of trees is merged, the formed
            // tree is left for later. After this pass we will have ceiling(size / 2) trees.

            // On the second pass, we will iterate back, so on the first pass we will maintain
            // a temporary list structure for iterating through (during the second pass).

            while (next != null)
            {
                // Take two trees from the list
                var a = next;
                var b = a.Next;

                // Is there a tree to merge 'a' with?
                if (b != null)
                {
                    next   = b.Next;
                    result = this.Merge(a, b);

                    // Maintain our temporary list for iterating in the second pass
                    result.Previous = tail;
                    tail            = result;
                }
                else
                {
                    a.Previous = tail;
                    tail       = a;
                    break;
                }
            }

            // On the second pass, iterate back (move right to left). Every time replace
            // the rightmost tree with the result of merging it with its predecessor.

            result = null;
            while (tail != null)
            {
                next   = tail.Previous;
                result = this.Merge(result, tail);
                tail   = next;
            }

            // Return a reference to the root of the resulting tree
            return(result);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Merges two heaps and returns the root of the resulting heap.
        /// </summary>
        private PairingHeapNode <TKey, TValue> Merge(PairingHeapNode <TKey, TValue> a, PairingHeapNode <TKey, TValue> b)
        {
            // If merging occurs between a non-empty pairing heap and an empty
            // pairing heap, merge just returns the non-empty pairing heap.

            if (a == null)
            {
                return(b);
            }

            if (b == null)
            {
                return(a);
            }

            if (a == b)
            {
                return(a);
            }

            // If both pairing heaps are non-empty, the merge function returns
            // a new heap where the smallest root of the two heaps is the root of
            // the new combined heap and adds the other heap to the list of its children.

            PairingHeapNode <TKey, TValue> parent, child;

            if (this.Comparer.Compare(a.Key, b.Key) < 0)
            {
                parent = a;
                child  = b;
            }
            else
            {
                parent = b;
                child  = a;
            }

            // The smallest root will be the new leftmost child of the largest root.
            // Thus, add it to the list of siblings and make a parent-child relation.

            child.Next = parent.Child;
            if (parent.Child != null)
            {
                parent.Child.Previous = child;
            }

            child.Previous = parent;
            parent.Child   = child;

            // Roots have no siblings, so adjust the pointers accordingly.
            parent.Next     = null;
            parent.Previous = null;

            return(parent);
        }
Ejemplo n.º 6
0
        /// <inheritdoc cref="IHeap{TKey,TValue}.Update"/>
        public override void Update(PairingHeapNode <TKey, TValue> node, TKey key)
        {
            if (node == null)
            {
                throw new ArgumentNullException(nameof(node));
            }

            var relation = this.Comparer.Compare(key, node.Key);

            node.Key = key;

            // If the new value is considered equal to the previous value, there is no need
            // to fix the heap property, because it is already preserved.

            if (relation == 0)
            {
                return;
            }

            if (relation < 0)
            {
                // In case the root gets a value that should be extracted from the heap even
                // earlier, there is also no need to fix anything.

                if (node == this.Root)
                {
                    return;
                }

                node.RemoveFromListOfSiblings();
                this.Root = this.Merge(this.Root, node);
                return;
            }

            // In case the node was updated with a greater value, it is in the right spot.
            // However, the heap property might be violated for all its children. For that
            // reason we will merge them pairwisely to form a single tree and merge this
            // tree with our heap.

            var child = node.Child;

            if (child == null)
            {
                return;
            }

            node.Child     = null;
            child.Previous = null; // TODO: this line might be not needed

            var tree = this.MergePairwisely(child);

            this.Root = this.Merge(this.Root, tree);
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Removes the node from its list of siblings. The child is not affected.
        /// </summary>
        public void RemoveFromListOfSiblings()
        {
            // Depending on whether the node is the leftmost node or not, we should
            // update the 'child' pointer of the parent (for the leftmost node) or the
            // 'next' pointer of the previous sibling (for other nodes).

            if (this == this.Previous.Child)
            {
                this.Previous.Child = this.Next;
            }
            else
            {
                this.Previous.Next = this.Next;
            }

            // If the node is not the last element in the list of siblings, we also
            // need to fix the 'previous' pointer of the next sibling.

            if (this.Next != null)
            {
                this.Next.Previous = this.Previous;
            }
        }