/// <summary>
        /// Removes the given node from this queue if it is present.
        /// </summary>
        /// <param name="node">
        /// The node to remove if present.
        /// </param>
        /// <returns>
        /// A value indicating whether the node was removed.
        /// </returns>
        public bool Remove(PriorityQueueNode <TPriority, TData> node)
        {
            if (!this.Contains(node))
            {
                return(false);
            }

            if (this.Count <= 1)
            {
                this.nodes[1] = null;
                this.Count    = 0;
                return(true);
            }

            bool wasSwapped     = false;
            var  formerLastNode = this.nodes[this.Count];

            if (node.QueueIndex != this.Count)
            {
                this.Swap(node, formerLastNode);
                wasSwapped = true;
            }

            --this.Count;
            this.nodes[node.QueueIndex] = null;

            if (wasSwapped)
            {
                this.OnNodeUpdated(formerLastNode);
            }

            return(true);
        }
        private void Swap(PriorityQueueNode <TPriority, TData> node1, PriorityQueueNode <TPriority, TData> node2)
        {
            this.nodes[node1.QueueIndex] = node2;
            this.nodes[node2.QueueIndex] = node1;

            int temp = node1.QueueIndex;

            node1.QueueIndex = node2.QueueIndex;
            node2.QueueIndex = temp;
        }
        /// <summary>
        /// Changes the priority of the given node.
        /// </summary>
        /// <param name="node">
        /// The node whose priority to change.
        /// </param>
        /// <param name="priority">
        /// The new priority for the node.
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="node"/> is <see langword="null"/>.
        /// </exception>
        public void ChangePriority(PriorityQueueNode <TPriority, TData> node, TPriority priority)
        {
            if (node == null)
            {
                throw new ArgumentNullException("node");
            }

            node.Priority = priority;
            this.OnNodeUpdated(node);
        }
        private void OnNodeUpdated(PriorityQueueNode <TPriority, TData> node)
        {
            int parentIndex = node.QueueIndex / 2;
            var parentNode  = this.nodes[parentIndex];

            if (parentIndex > 0 && this.HasHigherPriority(node, parentNode))
            {
                this.HeapifyUp(node);
            }
            else
            {
                this.HeapifyDown(node);
            }
        }
        private void HeapifyDown(PriorityQueueNode <TPriority, TData> node)
        {
            int finalQueueIndex = node.QueueIndex;

            while (true)
            {
                var newParent      = node;
                int childLeftIndex = 2 * finalQueueIndex;

                if (childLeftIndex > this.Count)
                {
                    node.QueueIndex             = finalQueueIndex;
                    this.nodes[finalQueueIndex] = node;
                    break;
                }

                var childLeft = this.nodes[childLeftIndex];
                if (this.HasHigherPriority(childLeft, newParent))
                {
                    newParent = childLeft;
                }

                int childRightIndex = childLeftIndex + 1;
                if (childRightIndex <= this.Count)
                {
                    var childRight = this.nodes[childRightIndex];
                    if (this.HasHigherPriority(childRight, newParent))
                    {
                        newParent = childRight;
                    }
                }

                if (newParent != node)
                {
                    this.nodes[finalQueueIndex] = newParent;

                    int temp = newParent.QueueIndex;
                    newParent.QueueIndex = finalQueueIndex;
                    finalQueueIndex      = temp;
                }
                else
                {
                    node.QueueIndex             = finalQueueIndex;
                    this.nodes[finalQueueIndex] = node;
                    break;
                }
            }
        }
        private void HeapifyUp(PriorityQueueNode <TPriority, TData> node)
        {
            int parent = node.QueueIndex / 2;

            while (parent >= 1)
            {
                var parentNode = this.nodes[parent];
                if (this.HasHigherPriority(parentNode, node))
                {
                    break;
                }

                this.Swap(node, parentNode);

                parent = node.QueueIndex / 2;
            }
        }
        /// <summary>
        /// Adds a given node to the queue with the given priority.
        /// </summary>
        /// <param name="node">
        /// The node to add to the queue.
        /// </param>
        /// <param name="priority">
        /// The priority for the node.
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="node"/> is <see langword="null"/>.
        /// </exception>
        public void Enqueue(PriorityQueueNode <TPriority, TData> node, TPriority priority)
        {
            if (node == null)
            {
                throw new ArgumentNullException("node");
            }

            node.Priority   = priority;
            node.QueueIndex = ++this.Count;

            if (this.nodes.Count <= this.Count)
            {
                this.nodes.Add(null);
            }

            this.nodes[this.Count] = node;
            this.HeapifyUp(this.nodes[this.Count]);
        }
Ejemplo n.º 8
0
        /// <summary>Insert into the priority queue. Duplicates are allowed.
        /// </summary>
        /// <param name="x">The item to insert.</param>
        public void Add(T x)
        {
            var node = new PriorityQueueNode <T, T>(x);

            this._queue.Enqueue(node, x);
        }
 private bool HasHigherPriority(PriorityQueueNode <TPriority, TData> higher, PriorityQueueNode <TPriority, TData> lower)
 {
     // The "higher-priority" item is actually the item whose priority
     // compares *lower*, because this is a min-heap.
     return(this.priorityComparer.Compare(higher.Priority, lower.Priority) < 0);
 }
 /// <summary>
 /// Determines whether the given node is contained within this queue.
 /// </summary>
 /// <param name="node">
 /// The node to locate in the queue.
 /// </param>
 /// <returns>
 /// <see langword="true"/> if <paramref name="node"/> is found in the
 /// queue, otherwise <see langword="false"/>.
 /// </returns>
 public bool Contains(PriorityQueueNode <TPriority, TData> node)
 {
     return(node != null &&
            node.QueueIndex < this.nodes.Count &&
            this.nodes[node.QueueIndex] == node);
 }