BinaryHeap.cs 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. using System;
  2. using UnityEngine;
  3. namespace Unity.Services.Core.Scheduler.Internal
  4. {
  5. class MinimumBinaryHeap<T> where T : IComparable<T>
  6. {
  7. const float k_IncreaseFactor = 1.5f;
  8. const float k_DecreaseFactor = 2.0f;
  9. readonly int m_MinimumCapacity;
  10. T[] m_HeapArray;
  11. int m_Count;
  12. public int Count => m_Count;
  13. public T Min => m_HeapArray[0];
  14. public MinimumBinaryHeap(int capacity = 10)
  15. {
  16. if (capacity <= 0)
  17. {
  18. throw new ArgumentException("capacity must be more than 0");
  19. }
  20. m_MinimumCapacity = capacity;
  21. m_HeapArray = new T[capacity];
  22. m_Count = 0;
  23. }
  24. public void Insert(T data)
  25. {
  26. IncreaseHeapCapacityWhenFull();
  27. var dataPos = m_Count;
  28. m_HeapArray[m_Count] = data;
  29. m_Count++;
  30. while (dataPos != 0 && m_HeapArray[dataPos].CompareTo(m_HeapArray[Parent(dataPos)]) < 0)
  31. {
  32. Swap(ref m_HeapArray[dataPos], ref m_HeapArray[Parent(dataPos)]);
  33. dataPos = Parent(dataPos);
  34. }
  35. }
  36. void IncreaseHeapCapacityWhenFull()
  37. {
  38. if (m_Count == m_HeapArray.Length)
  39. {
  40. int newCapacity = (int)Math.Ceiling(Count * k_IncreaseFactor);
  41. T[] newHeapArray = new T[newCapacity];
  42. Array.Copy(m_HeapArray, newHeapArray, m_Count);
  43. m_HeapArray = newHeapArray;
  44. }
  45. }
  46. public void Remove(T data)
  47. {
  48. var key = GetKey(data);
  49. while (key != 0)
  50. {
  51. Swap(ref m_HeapArray[key],
  52. ref m_HeapArray[Parent(key)]);
  53. key = Parent(key);
  54. }
  55. ExtractMin();
  56. }
  57. public T ExtractMin()
  58. {
  59. if (m_Count <= 0)
  60. {
  61. throw new InvalidOperationException("Can not ExtractMin: BinaryHeap is empty.");
  62. }
  63. var data = m_HeapArray[0];
  64. if (m_Count == 1)
  65. {
  66. m_Count--;
  67. m_HeapArray[0] = default;
  68. return data;
  69. }
  70. m_Count--;
  71. m_HeapArray[0] = m_HeapArray[m_Count];
  72. m_HeapArray[m_Count] = default;
  73. MinHeapify(0);
  74. DecreaseHeapCapacityWhenSpare();
  75. return data;
  76. }
  77. void DecreaseHeapCapacityWhenSpare()
  78. {
  79. if (m_Count > m_MinimumCapacity && m_Count < m_HeapArray.Length / k_DecreaseFactor)
  80. {
  81. T[] newHeapArray = new T[m_Count];
  82. Array.Copy(m_HeapArray, newHeapArray, m_Count);
  83. m_HeapArray = newHeapArray;
  84. }
  85. }
  86. int GetKey(T data)
  87. {
  88. var key = -1;
  89. for (var i = 0; i < m_Count; i++)
  90. {
  91. if (m_HeapArray[i].Equals(data))
  92. {
  93. key = i;
  94. break;
  95. }
  96. }
  97. return key;
  98. }
  99. void MinHeapify(int key)
  100. {
  101. int leftKey = LeftChild(key);
  102. int rightKey = RightChild(key);
  103. int smallest = key;
  104. if (leftKey < m_Count &&
  105. m_HeapArray[leftKey].CompareTo(m_HeapArray[smallest]) < 0)
  106. {
  107. smallest = leftKey;
  108. }
  109. if (rightKey < m_Count &&
  110. m_HeapArray[rightKey].CompareTo(m_HeapArray[smallest]) < 0)
  111. {
  112. smallest = rightKey;
  113. }
  114. if (smallest != key)
  115. {
  116. Swap(ref m_HeapArray[key],
  117. ref m_HeapArray[smallest]);
  118. MinHeapify(smallest);
  119. }
  120. }
  121. static void Swap(ref T lhs, ref T rhs)
  122. {
  123. T temp = lhs;
  124. lhs = rhs;
  125. rhs = temp;
  126. }
  127. static int Parent(int key)
  128. {
  129. return (key - 1) / 2;
  130. }
  131. static int LeftChild(int key)
  132. {
  133. return 2 * key + 1;
  134. }
  135. static int RightChild(int key)
  136. {
  137. return 2 * key + 2;
  138. }
  139. }
  140. }