public TPriority FrontPriority()
        {
            // assumes pq is not empty; up to calling code
            StablePriorityQueueItem <TPriority, TValue> frontItem = this.data[0];   // fetch the front

            return(frontItem.Priority);
        }
        private void DeleteAt(int index)
        {
            int lastIndex = this.data.Count - 1; // last index (before removal)

            this.data[index] = this.data[lastIndex];
            this.data.RemoveAt(lastIndex);

            lastIndex--;        // last index (after removal)
            int parent = index; // parent index. start at front of pq

            while (true)
            {
                int child = (parent * 2) + 1; // left child index of parent
                if (child > lastIndex)
                {
                    break;                                        // no children so done
                }
                int rc = child + 1;                               // right child
                if (rc <= lastIndex && !this.IsLarger(rc, child)) // if there is a rc (ci + 1), and it is smaller than left child, use the rc instead
                {
                    child = rc;
                }
                if (!this.IsLarger(parent, child))
                {
                    break; // parent is smaller than (or equal to) smallest child so done
                }
                StablePriorityQueueItem <TPriority, TValue> tmp = this.data[parent];
                this.data[parent] = this.data[child];
                this.data[child]  = tmp; // swap parent and child
                parent            = child;
            }
        }
        public TValue Dequeue()
        {
            // assumes pq is not empty; up to calling code
            StablePriorityQueueItem <TPriority, TValue> frontItem = this.data[0];   // fetch the front

            this.DeleteAt(0);

            return(frontItem.Value);
        }
        public void Enqueue(TPriority priority, TValue item)
        {
            this.data.Add(new StablePriorityQueueItem <TPriority, TValue>(priority, this.insertions, item));
            this.insertions++;

            int child = this.data.Count - 1; // child index; start at end

            while (child > 0)
            {
                int parent = (child - 1) / 2; // parent index
                if (this.IsLarger(child, parent))
                {
                    break; // child item is larger than (or equal) parent so we're done
                }
                StablePriorityQueueItem <TPriority, TValue> tmp = this.data[child];
                this.data[child]  = this.data[parent];
                this.data[parent] = tmp;
                child             = parent;
            }
        }
        public void AddOrSetPriority(TPriority priority, TValue item)
        {
            bool isInQueue = false;

            // search for item
            for (int ii = 0; ii < this.data.Count; ii++)
            {
                if (this.data[ii].Value.Equals(item))
                {
                    // if item is found, delete it
                    isInQueue = true;
                    this.DeleteAt(ii);
                    break;
                }
            }

            // re-add item
            if (!isInQueue)
            {
                this.insertions++;
            }

            this.data.Add(new StablePriorityQueueItem <TPriority, TValue>(priority, this.insertions, item));
            int child = this.data.Count - 1; // child index; start at end

            while (child > 0)
            {
                int parent = (child - 1) / 2; // parent index
                if (this.IsLarger(child, parent))
                {
                    break; // child item is larger than (or equal) parent so we're done
                }
                StablePriorityQueueItem <TPriority, TValue> tmp = this.data[child];
                this.data[child]  = this.data[parent];
                this.data[parent] = tmp;
                child             = parent;
            }
        }