public PriorityQueueNode <T> Enqueue(T item) { var result = new PriorityQueueNode <T>(item); Enqueue(result); return(result); }
/// <summary>Add an element to the priority queue - O(log(n)) time operation.</summary> /// <param name="item">The item to be added to the queue</param> public void Enqueue([NotNull] PriorityQueueNode <T> item) { if (item.Index != -1) { throw new InvalidOperationException("Item belongs to another PriorityNodeQueue."); } // We add the item to the end of the list (at the bottom of the // tree). Then, the heap-property could be violated between this element // and it's parent. If this is the case, we swap this element with the // parent (a safe operation to do since the element is known to be less // than it's parent). Now the element move one level up the tree. We repeat // this test with the element and it's new parent. The element, if lesser // than everybody else in the tree will eventually bubble all the way up // to the root of the tree (or the head of the list). It is easy to see // this will take log(N) time, since we are working with a balanced binary // tree. var n = items.Count; items.Add(item); item.Index = n; while (n != 0) { var p = n / 2; // This is the 'parent' of this item if (comparer.Compare(items[n].Value, items[p].Value) >= 0) { break; // Item >= parent } // Swap item and parent var tmp = items[n]; var tmp2 = items[p]; tmp2.Index = n; tmp.Index = p; items[n] = tmp2; items[p] = tmp; n = p; // And continue } }
/// <summary> /// Removes the specified item. /// </summary> /// <param name="item">The item to remove.</param> public void Remove([NotNull] PriorityQueueNode <T> item) { var index = item.Index; if (index == -1) { return; } // The element to return is of course the first element in the array, // or the root of the tree. However, this will leave a 'hole' there. We // fill up this hole with the last element from the array. This will // break the heap property. So we bubble the element downwards by swapping // it with it's lower child until it reaches it's correct level. The lower // child (one of the orignal elements with index 1 or 2) will now be at the // head of the queue (root of the tree). var nMax = items.Count - 1; var itemMax = items[nMax]; itemMax.Index = index; var itemToRemove = items[index]; itemToRemove.Index = -1; items[index] = itemMax; items.RemoveAt(nMax); // Move the last element to the top var p = index; while (true) { // c is the child we want to swap with. If there // is no child at all, then the heap is balanced var c = p * 2; if (c >= nMax) { break; } // If the second child is smaller than the first, that's the one // we want to swap with this parent. if (c + 1 < nMax && comparer.Compare(items[c + 1].Value, items[c].Value) < 0) { c++; } // If the parent is already smaller than this smaller child, then // we are done if (comparer.Compare(items[p].Value, items[c].Value) <= 0) { break; } // Othewise, swap parent and child, and follow down the parent var tmp = items[p]; var tmp2 = items[c]; tmp.Index = c; tmp2.Index = p; items[p] = tmp2; items[c] = tmp; p = c; } item.Index = -1; }