summaryrefslogtreecommitdiff
path: root/Assets/CollectionsExt/MaxHeap.cs
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2021-06-24 19:55:26 +0800
committerchai <chaifix@163.com>2021-06-24 19:55:26 +0800
commitdbcd0c269014100b7d4cc421c5ab518f275cca09 (patch)
tree6564ca8a58b6921d4782bba3feae0ea787f9e1f4 /Assets/CollectionsExt/MaxHeap.cs
parent2749e059084b99737d79aadd92521023b0f65f56 (diff)
Diffstat (limited to 'Assets/CollectionsExt/MaxHeap.cs')
-rw-r--r--Assets/CollectionsExt/MaxHeap.cs158
1 files changed, 158 insertions, 0 deletions
diff --git a/Assets/CollectionsExt/MaxHeap.cs b/Assets/CollectionsExt/MaxHeap.cs
new file mode 100644
index 0000000..09066f1
--- /dev/null
+++ b/Assets/CollectionsExt/MaxHeap.cs
@@ -0,0 +1,158 @@
+using System;
+using System.Collections.Generic;
+
+namespace CollectionsExt
+{
+ // 最大堆
+ public class MaxHeap<T>
+ {
+ private const int InitialCapacity = 4;
+
+ private T[] _arr;
+ private int _lastItemIndex;
+ private IComparer<T> _comparer;
+
+ public MaxHeap()
+ : this(InitialCapacity, Comparer<T>.Default)
+ {
+ }
+
+ public MaxHeap(int capacity)
+ : this(capacity, Comparer<T>.Default)
+ {
+ }
+
+ public MaxHeap(Comparison<T> comparison)
+ : this(InitialCapacity, Comparer<T>.Create(comparison))
+ {
+ }
+
+ public MaxHeap(IComparer<T> comparer)
+ : this(InitialCapacity, comparer)
+ {
+ }
+
+ public MaxHeap(int capacity, IComparer<T> comparer)
+ {
+ _arr = new T[capacity];
+ _lastItemIndex = -1;
+ _comparer = comparer;
+ }
+
+ public int Count
+ {
+ get
+ {
+ return _lastItemIndex + 1;
+ }
+ }
+
+ public void Add(T item)
+ {
+ if (_lastItemIndex == _arr.Length - 1)
+ {
+ Resize();
+ }
+
+ _lastItemIndex++;
+ _arr[_lastItemIndex] = item;
+
+ MaxHeapifyUp(_lastItemIndex);
+ }
+
+ public T Remove()
+ {
+ if (_lastItemIndex == -1)
+ {
+ throw new InvalidOperationException("The heap is empty");
+ }
+
+ T removedItem = _arr[0];
+ _arr[0] = _arr[_lastItemIndex];
+ _lastItemIndex--;
+
+ MaxHeapifyDown(0);
+
+ return removedItem;
+ }
+
+ public T Peek()
+ {
+ if (_lastItemIndex == -1)
+ {
+ throw new InvalidOperationException("The heap is empty");
+ }
+
+ return _arr[0];
+ }
+
+ public void Clear()
+ {
+ _lastItemIndex = -1;
+ }
+
+ // 堆顶是最小值
+ private void MaxHeapifyUp(int index)
+ {
+ if (index == 0)
+ {
+ return;
+ }
+
+ int childIndex = index;
+ int parentIndex = (index - 1) / 2;
+
+ // 堆顶是最小值
+ if (_comparer.Compare(_arr[childIndex], _arr[parentIndex]) > 0)
+ {
+ // swap the parent and the child
+ T temp = _arr[childIndex];
+ _arr[childIndex] = _arr[parentIndex];
+ _arr[parentIndex] = temp;
+
+ // 递归
+ MaxHeapifyUp(parentIndex);
+ }
+ }
+
+ private void MaxHeapifyDown(int index)
+ {
+ int leftChildIndex = index * 2 + 1;
+ int rightChildIndex = index * 2 + 2;
+ int biggestItemIndex = index; // The index of the parent
+
+ if (leftChildIndex <= _lastItemIndex &&
+ _comparer.Compare(_arr[leftChildIndex], _arr[biggestItemIndex]) > 0)
+ {
+ biggestItemIndex = leftChildIndex;
+ }
+
+ if (rightChildIndex <= _lastItemIndex &&
+ _comparer.Compare(_arr[rightChildIndex], _arr[biggestItemIndex]) < 0)
+ {
+ biggestItemIndex = rightChildIndex;
+ }
+
+ if (biggestItemIndex != index)
+ {
+ // swap the parent with the biggest of the child items
+ T temp = _arr[index];
+ _arr[index] = _arr[biggestItemIndex];
+ _arr[biggestItemIndex] = temp;
+
+ MaxHeapifyDown(biggestItemIndex);
+ }
+ }
+
+ private void Resize()
+ {
+ T[] newArr = new T[_arr.Length * 2];
+ for (int i = 0; i < _arr.Length; i++)
+ {
+ newArr[i] = _arr[i];
+ }
+
+ _arr = newArr;
+ }
+ }
+}