using System.Collections.Generic;
public static void Main()
var words = "Now is the time for all good men to come to the aid of their country".Split(' ');
var heap = new BinaryMinHeap<string, int>(words, w => w.Length);
public class BinaryMinHeap<TValue, TPriority>
where TPriority : IComparable<TPriority>
public TPriority Priority;
private readonly List<Node> Nodes = new List<Node>();
private readonly Dictionary<TValue, int> NodeIndexes = new Dictionary<TValue, int>();
private static int ParentIndex(int i) { return (i - 1) / 2; }
private static int LeftChildIndex(int i) { return 2 * i + 1; }
private static int RightChildIndex(int i) { return 2 * i + 2; }
public BinaryMinHeap(IEnumerable<TValue> items, Func<TValue, TPriority> prioritySelector)
foreach (var item in items)
NodeIndexes[item] = Nodes.Count;
Priority = prioritySelector(item),
for (var i = ParentIndex(Nodes.Count - 1); i >= 0; i -= 1)
private bool ShouldSwap(int parentIndex, int childIndex)
return childIndex < Nodes.Count
&& Nodes[parentIndex].Priority.CompareTo(Nodes[childIndex].Priority) > 0;
private void Swap(int i, int j)
NodeIndexes[Nodes[j].Item] = i;
NodeIndexes[temp.Item] = j;
private void SiftDown(int parentIndex)
while (parentIndex * 2 < Nodes.Count)
var leftChildIndex = LeftChildIndex(parentIndex);
var rightChildIndex = RightChildIndex(parentIndex);
var swapWith = parentIndex;
if (ShouldSwap(swapWith, leftChildIndex))
swapWith = leftChildIndex;
if (ShouldSwap(swapWith, rightChildIndex))
swapWith = rightChildIndex;
if (swapWith != parentIndex)
Swap(parentIndex, swapWith);
private void SiftUp(int childIndex)
var parentIndex = ParentIndex(childIndex);
if (ShouldSwap(parentIndex, childIndex))
Swap(parentIndex, childIndex);
childIndex = parentIndex;
var lastIndex = Nodes.Count - 1;
var minimum = Nodes[lastIndex].Item;
Nodes.RemoveAt(lastIndex);
public void DecreasePriority(TValue item, TPriority newPriority)
if (!NodeIndexes.TryGetValue(item, out index))
throw new KeyNotFoundException(string.Format("Cannot find item in heap! Item: {0}", item));
if (!item.Equals(node.Item))
throw new Exception(string.Format("This heap implementation sucks. Expected to find {0} at index {1}, but found {2} instead.", item, index, node.Item));
if (newPriority.CompareTo(node.Priority) > 0)
throw new InvalidOperationException(string.Format("Cannot increase priority value! Item: {0}, old priority: {1}, new priority: {2}", item, node.Priority, newPriority));