Beispiel #1
0
        /// <summary>
        /// Moves a node up in the tree to restore heap order.
        /// </summary>
        /// <param name="node">The node to be moved up.</param>
        private void MoveUp(ArrayHeapNode <TKey, TValue> node)
        {
            var i = node.Index;

            // Instead of swapping items all the way to the root, we will perform
            // a similar optimization as in the insertion sort.

            while (i > 0)
            {
                var parentIndex = this.GetParentIndex(i);
                var parent      = this.nodes[parentIndex];

                if (this.Comparer.Compare(node.Key, parent.Key) < 0)
                {
                    this.PutAt(parent, i);
                    i = parentIndex;
                }
                else
                {
                    break;
                }
            }

            this.PutAt(node, i);
        }
Beispiel #2
0
        /// <inheritdoc cref="IHeap{TKey,TValue}.Add"/>
        public override ArrayHeapNode <TKey, TValue> Add(TKey key, TValue value)
        {
            // Add node at the end
            var node = new ArrayHeapNode <TKey, TValue>(key, value, this.Count);

            this.nodes.Add(node);

            // Restore the heap order
            this.MoveUp(node);
            return(node);
        }
Beispiel #3
0
        /// <summary>
        /// Moves a node down in the tree to restore heap order.
        /// </summary>
        /// <param name="node">The node to be moved down.</param>
        private void MoveDown(ArrayHeapNode <TKey, TValue> node)
        {
            // The node to move down will not actually be swapped every time.
            // Rather, values on the affected path will be moved up, thus leaving a free spot
            // for this value to drop in. Similar optimization as in the insertion sort.
            var index = node.Index;

            int i;

            while ((i = this.GetFirstChildIndex(index)) < this.Count)
            {
                // Check if the current node (pointed by 'index') should really be extracted
                // first, or maybe one of its children should be extracted earlier.
                var topChild             = this.nodes[i];
                var childrenIndexesLimit = Math.Min(i + this.Arity, this.Count);

                while (++i < childrenIndexesLimit)
                {
                    var child = this.nodes[i];
                    if (this.Comparer.Compare(child.Key, topChild.Key) < 0)
                    {
                        topChild = child;
                    }
                }

                // In case no child needs to be extracted earlier than the current node,
                // there is nothing more to do - the right spot was found.
                if (this.Comparer.Compare(node.Key, topChild.Key) <= 0)
                {
                    break;
                }

                // Move the top child up by one node and now investigate the
                // node that was considered to be the top child (recursive).
                var topChildIndex = topChild.Index;
                this.PutAt(topChild, index);

                index = topChildIndex;
            }

            this.PutAt(node, index);
        }
Beispiel #4
0
        /// <inheritdoc cref="IHeap{TKey,TValue}.Remove"/>
        public override TValue Remove(ArrayHeapNode <TKey, TValue> node)
        {
            if (node == null)
            {
                throw new ArgumentNullException(nameof(node));
            }

            // The idea is to replace the specified node by the very last
            // node and shorten the array by one.

            var lastNode = this.nodes[this.Count - 1];

            this.nodes.RemoveAt(lastNode.Index);

            // In case we wanted to remove the node that was the last one,
            // we are done.

            if (node == lastNode)
            {
                return(node.Value);
            }

            // Our last node was erased from the array and needs to be
            // inserted again. Of course, we will overwrite the node we
            // wanted to remove. After that operation, we will need
            // to restore the heap property (in general).

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

            this.PutAt(lastNode, node.Index);

            if (relation < 0)
            {
                this.MoveUp(lastNode);
            }
            else
            {
                this.MoveDown(lastNode);
            }

            return(node.Value);
        }
Beispiel #5
0
        /// <inheritdoc cref="IHeap{TKey,TValue}.Update"/>
        public override void Update(ArrayHeapNode <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 (relation < 0)
            {
                this.MoveUp(node);
            }
            else
            {
                this.MoveDown(node);
            }
        }
Beispiel #6
0
 /// <summary>
 /// Puts a node at the specified index.
 /// </summary>
 private void PutAt(ArrayHeapNode <TKey, TValue> node, int index)
 {
     node.Index        = index;
     this.nodes[index] = node;
 }