void bubbleUpMax(int i) { if (i > 0) { T max = heap[i].last, iv = max; PriorityQueueHandle maxhandle = heap[i].lasthandle; int p = (i + 1) / 2 - 1; while (i > 0) { if (comparer.Compare(iv, max = heap[p = (i + 1) / 2 - 1].last) > 0) { updateLast(i, max, heap[p].lasthandle); max = iv; i = p; } else { break; } } updateLast(i, iv, maxhandle); } }
/// <summary> /// Replace an item with a handle in a priority queue with a new item. /// Typically used for changing the priority of some queued object. /// </summary> /// <param name="handle">The handle for the old item</param> /// <param name="item">The new item</param> /// <returns>The old item</returns> public T Replace(PriorityQueueHandle handle, T item) { int cell; bool isfirst; checkHandle(handle, out cell, out isfirst); if (size == 0) { throw new InvalidOperationException("Heap is empty"); } T retval; if (isfirst) { retval = heap[cell].first; heap[cell].first = item; if (size == 1) { } else if (size == 2 * cell + 1) // cell == lastcell { int p = (cell + 1) / 2 - 1; if (comparer.Compare(item, heap[p].last) > 0) { PriorityQueueHandle thehandle = heap[cell].firsthandle; updateFirst(cell, heap[p].last, heap[p].lasthandle); updateLast(p, item, thehandle); bubbleUpMax(p); } else { bubbleUpMin(cell); } } else if (heapifyMin(cell)) { bubbleUpMax(cell); } else { bubbleUpMin(cell); } } else { retval = heap[cell].last; heap[cell].last = item; if (heapifyMax(cell)) { bubbleUpMin(cell); } else { bubbleUpMax(cell); } } return(retval); }
/// <summary> /// Check safely if a handle is valid for this queue and if so, report the corresponding queue item. /// </summary> /// <param name="handle">The handle to check</param> /// <param name="item">If the handle is valid this will contain the corresponding item on output.</param> /// <returns>True if the handle is valid.</returns> public bool Find(PriorityQueueHandle handle, out T item) { PriorityQueueHandle myhandle = handle; if (myhandle == null) { item = default(T); return(false); } int toremove = myhandle.index; int cell = toremove / 2; bool isfirst = toremove % 2 == 0; { if (toremove == -1 || toremove >= size) { item = default(T); return(false); } PriorityQueueHandle actualhandle = isfirst ? heap[cell].firsthandle : heap[cell].lasthandle; if (actualhandle != myhandle) { item = default(T); return(false); } } item = isfirst ? heap[cell].first : heap[cell].last; return(true); }
void bubbleUpMin(int i) { if (i > 0) { T min = heap[i].first, iv = min; PriorityQueueHandle minhandle = heap[i].firsthandle; int p = (i + 1) / 2 - 1; while (i > 0) { if (comparer.Compare(iv, min = heap[p = (i + 1) / 2 - 1].first) < 0) { updateFirst(i, min, heap[p].firsthandle); min = iv; i = p; } else { break; } } updateFirst(i, iv, minhandle); } }
private bool add(PriorityQueueHandle itemhandle, T item) { if (size == 0) { size = 1; updateFirst(0, item, itemhandle); return(true); } if (size == 2 * heap.Length) { Interval[] newheap = new Interval[2 * heap.Length]; Array.Copy(heap, newheap, heap.Length); heap = newheap; } if (size % 2 == 0) { int i = size / 2, p = (i + 1) / 2 - 1; T tmp = heap[p].last; if (comparer.Compare(item, tmp) > 0) { updateFirst(i, tmp, heap[p].lasthandle); updateLast(p, item, itemhandle); bubbleUpMax(p); } else { updateFirst(i, item, itemhandle); if (comparer.Compare(item, heap[p].first) < 0) { bubbleUpMin(i); } } } else { int i = size / 2; T other = heap[i].first; if (comparer.Compare(item, other) < 0) { updateLast(i, other, heap[i].firsthandle); updateFirst(i, item, itemhandle); bubbleUpMin(i); } else { updateLast(i, item, itemhandle); bubbleUpMax(i); } } size++; return(true); }
/// <summary> /// Find the current least item of this priority queue. /// </summary> /// <param name="handle">On return: the handle of the item.</param> /// <returns>The least item.</returns> public T FindMin(out PriorityQueueHandle handle) { if (size == 0) { throw new InvalidOperationException("Heap is empty"); } handle = heap[0].firsthandle; return(heap[0].first); }
private void updateFirst(int cell, T item, PriorityQueueHandle handle) { heap[cell].first = item; if (handle != null) { handle.index = 2 * cell; } heap[cell].firsthandle = handle; }
/// <summary> /// Remove the largest item from this priority queue. /// </summary> /// <param name="handle">On return: the handle of the removed item.</param> /// <returns>The removed item.</returns> public T DeleteMax(out PriorityQueueHandle handle) { if (size == 0) { throw new InvalidOperationException("Heap is empty"); } T retval; PriorityQueueHandle myhandle; if (size == 1) { size = 0; retval = heap[0].first; myhandle = heap[0].firsthandle; if (myhandle != null) { myhandle.index = -1; } heap[0].first = default(T); heap[0].firsthandle = null; } else { retval = heap[0].last; myhandle = heap[0].lasthandle; if (myhandle != null) { myhandle.index = -1; } int lastcell = (size - 1) / 2; if (size % 2 == 0) { updateLast(0, heap[lastcell].last, heap[lastcell].lasthandle); heap[lastcell].last = default(T); heap[lastcell].lasthandle = null; } else { updateLast(0, heap[lastcell].first, heap[lastcell].firsthandle); heap[lastcell].first = default(T); heap[lastcell].firsthandle = null; } size--; heapifyMax(0); } handle = myhandle; return(retval); }
/// <summary> /// Get or set the item corresponding to a handle. /// </summary> /// <param name="handle">The reference into the heap</param> /// <returns></returns> public T this[PriorityQueueHandle handle] { get { int cell; bool isfirst; checkHandle(handle, out cell, out isfirst); return(isfirst ? heap[cell].first : heap[cell].last); } set { Replace(handle, value); } }
/// <summary> /// Add an item to the priority queue, receiving a /// handle for the item in the queue, /// or reusing an already existing handle. /// </summary> /// <param name="handle">On output: a handle for the added item. /// On input: null for allocating a new handle, an invalid handle for reuse. /// A handle for reuse must be compatible with this priority queue, /// by being created by a priority queue of the same runtime type, but not /// necessarily the same priority queue object.</param> /// <param name="item">The item to add.</param> /// <returns>True since item will always be added unless the call throws an exception.</returns> public bool Add(ref PriorityQueueHandle handle, T item) { PriorityQueueHandle myhandle = handle; if (myhandle == null) { handle = myhandle = new PriorityQueueHandle(); } else if (myhandle.index != -1) { throw new ArgumentException("Handle not valid for reuse"); } if (add(myhandle, item)) { return(true); } return(false); }
private PriorityQueueHandle checkHandle(PriorityQueueHandle handle, out int cell, out bool isfirst) { PriorityQueueHandle myhandle = handle; int toremove = myhandle.index; cell = toremove / 2; isfirst = toremove % 2 == 0; { if (toremove == -1 || toremove >= size) { throw new ArgumentException("Invalid handle, index out of range"); } PriorityQueueHandle actualhandle = isfirst ? heap[cell].firsthandle : heap[cell].lasthandle; if (actualhandle != myhandle) { throw new ArgumentException("Invalid handle, doesn't match queue"); } } return(myhandle); }
/// <summary> /// Delete an item with a handle from a priority queue. /// </summary> /// <param name="handle">The handle for the item. The handle will be invalidated, but reusable.</param> /// <returns>The deleted item</returns> public T Delete(PriorityQueueHandle handle) { int cell; bool isfirst; PriorityQueueHandle myhandle = checkHandle(handle, out cell, out isfirst); T retval; myhandle.index = -1; int lastcell = (size - 1) / 2; if (cell == lastcell) { if (isfirst) { retval = heap[cell].first; if (size % 2 == 0) { updateFirst(cell, heap[cell].last, heap[cell].lasthandle); heap[cell].last = default(T); heap[cell].lasthandle = null; } else { heap[cell].first = default(T); heap[cell].firsthandle = null; } } else { retval = heap[cell].last; heap[cell].last = default(T); heap[cell].lasthandle = null; } size--; } else if (isfirst) { retval = heap[cell].first; if (size % 2 == 0) { updateFirst(cell, heap[lastcell].last, heap[lastcell].lasthandle); heap[lastcell].last = default(T); heap[lastcell].lasthandle = null; } else { updateFirst(cell, heap[lastcell].first, heap[lastcell].firsthandle); heap[lastcell].first = default(T); heap[lastcell].firsthandle = null; } size--; if (heapifyMin(cell)) { bubbleUpMax(cell); } else { bubbleUpMin(cell); } } else { retval = heap[cell].last; if (size % 2 == 0) { updateLast(cell, heap[lastcell].last, heap[lastcell].lasthandle); heap[lastcell].last = default(T); heap[lastcell].lasthandle = null; } else { updateLast(cell, heap[lastcell].first, heap[lastcell].firsthandle); heap[lastcell].first = default(T); heap[lastcell].firsthandle = null; } size--; if (heapifyMax(cell)) { bubbleUpMin(cell); } else { bubbleUpMax(cell); } } return(retval); }
/// <summary> /// Remove the largest item from this priority queue. /// </summary> /// <returns>The removed item.</returns> public T DeleteMax() { PriorityQueueHandle handle = null; return(DeleteMax(out handle)); }
bool heapifyMax(int i) { bool swappedroot = false; int cell = i, currentmax = cell; T currentitem = heap[cell].last; PriorityQueueHandle currenthandle = heap[cell].lasthandle; if (i > 0) { T other = heap[cell].first; if (comparer.Compare(currentitem, other) < 0) { swappedroot = true; PriorityQueueHandle otherhandle = heap[cell].firsthandle; updateFirst(cell, currentitem, currenthandle); currentitem = other; currenthandle = otherhandle; } } T maxitem = currentitem; PriorityQueueHandle maxhandle = currenthandle; while (true) { int l = 2 * cell + 1, r = l + 1; T lv, rv; if (2 * l + 1 < size && comparer.Compare(lv = heap[l].last, maxitem) > 0) { currentmax = l; maxitem = lv; } if (2 * r + 1 < size && comparer.Compare(rv = heap[r].last, maxitem) > 0) { currentmax = r; maxitem = rv; } if (currentmax == cell) { break; } maxhandle = heap[currentmax].lasthandle; updateLast(cell, maxitem, maxhandle); cell = currentmax; //Maybe swap first and last T other = heap[cell].first; if (comparer.Compare(currentitem, other) < 0) { PriorityQueueHandle otherhandle = heap[cell].firsthandle; updateFirst(cell, currentitem, currenthandle); currentitem = other; currenthandle = otherhandle; } maxitem = currentitem; maxhandle = currenthandle; } if (cell != i || swappedroot) //Check could be better? { updateLast(cell, maxitem, maxhandle); } return(swappedroot); }
bool heapifyMin(int i) { bool swappedroot = false; int cell = i, currentmin = cell; T currentitem = heap[cell].first; PriorityQueueHandle currenthandle = heap[cell].firsthandle; if (i > 0) { T other = heap[cell].last; if (2 * cell + 1 < size && comparer.Compare(currentitem, other) > 0) { swappedroot = true; PriorityQueueHandle otherhandle = heap[cell].lasthandle; updateLast(cell, currentitem, currenthandle); currentitem = other; currenthandle = otherhandle; } } T minitem = currentitem; PriorityQueueHandle minhandle = currenthandle; while (true) { int l = 2 * cell + 1, r = l + 1; T lv, rv; if (2 * l < size && comparer.Compare(lv = heap[l].first, minitem) < 0) { currentmin = l; minitem = lv; } if (2 * r < size && comparer.Compare(rv = heap[r].first, minitem) < 0) { currentmin = r; minitem = rv; } if (currentmin == cell) { break; } minhandle = heap[currentmin].firsthandle; updateFirst(cell, minitem, minhandle); cell = currentmin; //Maybe swap first and last T other = heap[cell].last; if (2 * currentmin + 1 < size && comparer.Compare(currentitem, other) > 0) { PriorityQueueHandle otherhandle = heap[cell].lasthandle; updateLast(cell, currentitem, currenthandle); currentitem = other; currenthandle = otherhandle; } minitem = currentitem; minhandle = currenthandle; } if (cell != i || swappedroot) { updateFirst(cell, minitem, minhandle); } return(swappedroot); }