using System.Linq; namespace System.Collections.Generic { /// /// Binary heap implementation. /// /// Provided type. [Serializable] public sealed class BinaryHeap : IEnumerable where T : IComparable { #region Fields T[] items; private int capacity; private int count; private readonly int initialCapacity; #endregion #region Properties /// /// Minimum value from the heap. /// public T Min { get { return items[1]; } } /// /// Maximum value from the heap. /// public T Max { get { return items[count]; } } /// /// Capacity of the heap. /// public int Capacity { get => capacity; set { if (value > capacity) { Array.Resize(ref items, value); capacity = value; } } } /// /// Number of elements in the heap. /// public int Count { get => count; } #endregion #region Constructors /// /// Constructor for a binary heap data structure. /// public BinaryHeap() { capacity = 10; initialCapacity = capacity; items = new T[capacity]; } /// /// Constructor for a binary heap data structure. /// /// Initial capacity of the heap. Used for initial alocation of the array. public BinaryHeap(int capacity) { this.capacity = capacity; initialCapacity = capacity; items = new T[capacity]; } #endregion #region Public Methods /// /// Adds value to the queue. /// /// Value to be added. public void Add(T value) { if (count == Capacity - 1) { Capacity = 2 * Capacity; } var position = ++count; for (; position > 1 && value.CompareTo(items[position / 2]) < 0; position /= 2) { items[position] = items[position / 2]; } items[position] = value; } /// /// Removes the item at the root. Throws exception if there are no items in the heap. /// /// Value removed. public T Remove() { if (count == 0) { throw new IndexOutOfRangeException("Heap is empty!"); } var min = items[1]; items[1] = items[count--]; BubbleDown(1); return min; } /// /// Peeks at the item at the root. Throws exception if there are no items in the heap. /// /// public T Peek() { if (count == 0) { throw new IndexOutOfRangeException("Heap is empty!"); } var min = items[1]; return min; } /// /// Return the heap structure as an array /// /// Array with values sorted as in heap public T[] ToArray() { var newArray = new T[count]; Array.Copy(items, 1, newArray, 0, count); return newArray; } /// /// Determines whether the heap contains specified value /// /// Value to locate in the heap /// public bool Contains(T value) { return items.Contains(value); } /// /// Clears the heap /// public void Clear() { count = 0; } /// /// Clears the heap. /// /// Specifies if the underlying array should be cleared as well public void Clear(bool completeClear) { count = 0; if (completeClear) { capacity = initialCapacity; items = new T[initialCapacity]; } } /// /// Returns an enumerator that iterates over the heap. /// /// Enumerator that iterates over the heap. public IEnumerator GetEnumerator() { for (var i = 0; i < count; i++) { yield return items[i + 1]; } } #endregion #region Private Methods /// /// Bubble the specified element to its position /// /// Index of element to bubble private void BubbleDown(int index) { var temp = items[index]; int childIndex; for (; 2 * index <= count; index = childIndex) { childIndex = 2 * index; if (childIndex != Count && items[childIndex].CompareTo(items[childIndex + 1]) > 0) { childIndex++; } if (temp.CompareTo(items[childIndex]) > 0) { items[index] = items[childIndex]; } else { break; } } items[index] = temp; } /// /// Implementation of IEnumerator. /// /// Enumerator over the array. IEnumerator IEnumerable.GetEnumerator() { throw new NotImplementedException(); } #endregion } }