123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 |
- using System;
- using UnityEngine;
- namespace Unity.Services.Core.Scheduler.Internal
- {
- class MinimumBinaryHeap<T> where T : IComparable<T>
- {
- const float k_IncreaseFactor = 1.5f;
- const float k_DecreaseFactor = 2.0f;
- readonly int m_MinimumCapacity;
- T[] m_HeapArray;
- int m_Count;
- public int Count => m_Count;
- public T Min => m_HeapArray[0];
- public MinimumBinaryHeap(int capacity = 10)
- {
- if (capacity <= 0)
- {
- throw new ArgumentException("capacity must be more than 0");
- }
- m_MinimumCapacity = capacity;
- m_HeapArray = new T[capacity];
- m_Count = 0;
- }
- public void Insert(T data)
- {
- IncreaseHeapCapacityWhenFull();
- var dataPos = m_Count;
- m_HeapArray[m_Count] = data;
- m_Count++;
- while (dataPos != 0 && m_HeapArray[dataPos].CompareTo(m_HeapArray[Parent(dataPos)]) < 0)
- {
- Swap(ref m_HeapArray[dataPos], ref m_HeapArray[Parent(dataPos)]);
- dataPos = Parent(dataPos);
- }
- }
- void IncreaseHeapCapacityWhenFull()
- {
- if (m_Count == m_HeapArray.Length)
- {
- int newCapacity = (int)Math.Ceiling(Count * k_IncreaseFactor);
- T[] newHeapArray = new T[newCapacity];
- Array.Copy(m_HeapArray, newHeapArray, m_Count);
- m_HeapArray = newHeapArray;
- }
- }
- public void Remove(T data)
- {
- var key = GetKey(data);
- while (key != 0)
- {
- Swap(ref m_HeapArray[key],
- ref m_HeapArray[Parent(key)]);
- key = Parent(key);
- }
- ExtractMin();
- }
- public T ExtractMin()
- {
- if (m_Count <= 0)
- {
- throw new InvalidOperationException("Can not ExtractMin: BinaryHeap is empty.");
- }
- var data = m_HeapArray[0];
- if (m_Count == 1)
- {
- m_Count--;
- m_HeapArray[0] = default;
- return data;
- }
- m_Count--;
- m_HeapArray[0] = m_HeapArray[m_Count];
- m_HeapArray[m_Count] = default;
- MinHeapify(0);
- DecreaseHeapCapacityWhenSpare();
- return data;
- }
- void DecreaseHeapCapacityWhenSpare()
- {
- if (m_Count > m_MinimumCapacity && m_Count < m_HeapArray.Length / k_DecreaseFactor)
- {
- T[] newHeapArray = new T[m_Count];
- Array.Copy(m_HeapArray, newHeapArray, m_Count);
- m_HeapArray = newHeapArray;
- }
- }
- int GetKey(T data)
- {
- var key = -1;
- for (var i = 0; i < m_Count; i++)
- {
- if (m_HeapArray[i].Equals(data))
- {
- key = i;
- break;
- }
- }
- return key;
- }
- void MinHeapify(int key)
- {
- int leftKey = LeftChild(key);
- int rightKey = RightChild(key);
- int smallest = key;
- if (leftKey < m_Count &&
- m_HeapArray[leftKey].CompareTo(m_HeapArray[smallest]) < 0)
- {
- smallest = leftKey;
- }
- if (rightKey < m_Count &&
- m_HeapArray[rightKey].CompareTo(m_HeapArray[smallest]) < 0)
- {
- smallest = rightKey;
- }
- if (smallest != key)
- {
- Swap(ref m_HeapArray[key],
- ref m_HeapArray[smallest]);
- MinHeapify(smallest);
- }
- }
- static void Swap(ref T lhs, ref T rhs)
- {
- T temp = lhs;
- lhs = rhs;
- rhs = temp;
- }
- static int Parent(int key)
- {
- return (key - 1) / 2;
- }
- static int LeftChild(int key)
- {
- return 2 * key + 1;
- }
- static int RightChild(int key)
- {
- return 2 * key + 2;
- }
- }
- }
|