MaxHeap.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. class MaxHeap:
  2. def __init__(self, maxSize=None, isGreaterThan=None, smalestValue=(-1,0.0)):
  3. self.heap = []
  4. self.size = 0
  5. self.maxSize = maxSize
  6. self.isGreaterThan = isGreaterThan if isGreaterThan is not None else (lambda a, b: a > b)
  7. self.smalestValue = smalestValue
  8. self.indices = set()
  9. self.wasChanged = False
  10. self.insert(smalestValue)
  11. def copy(self):
  12. c = MaxHeap(maxSize=self.maxSize, isGreaterThan=self.isGreaterThan, smalestValue=self.smalestValue)
  13. c.heap = self.heap.copy()
  14. c.size = self.size
  15. c.indices = self.indices.copy()
  16. c.wasChanged = self.wasChanged
  17. return c
  18. def insert(self, v):
  19. if self.maxSize is not None and self.size >= self.maxSize:
  20. return self.replaceMax(v)
  21. if v[0] in self.indices:
  22. return False
  23. self.indices.add(v[0])
  24. pos = self.size
  25. self.size += 1
  26. self.heap.append(v)
  27. while pos > 0:
  28. w = self.heap[pos // 2]
  29. if not self.isGreaterThan(v, w):
  30. break
  31. self.heap[pos] = w
  32. pos = pos // 2
  33. self.heap[pos] = v
  34. self.wasChanged = True
  35. return True
  36. def childPos(self, pos):
  37. c = (pos + 1) * 2
  38. return (c - 1, c)
  39. def removeMax(self):
  40. if self.heap == []:
  41. self.size = 0
  42. return False
  43. if self.size <= 1:
  44. self.size = 0
  45. self.heap = []
  46. return True
  47. x = self.heap[0]
  48. self.indices.remove(x[0])
  49. self.heap[0] = self.heap[-1]
  50. self.heap = self.heap[:-1]
  51. self.size -= 1
  52. x = self.heap[0]
  53. pos = 0
  54. size = self.size
  55. while pos < size:
  56. (left, right) = self.childPos(pos)
  57. if left >= size:
  58. break
  59. y = self.heap[left]
  60. if right >= size:
  61. if self.isGreaterThan(y, x):
  62. self.heap[pos] = y
  63. self.heap[left] = x
  64. break
  65. z = self.heap[right]
  66. (best, v) = (left, y) if self.isGreaterThan(y, z) else (right, z)
  67. if not self.isGreaterThan(v, x):
  68. break
  69. self.heap[pos] = v
  70. self.heap[best] = x
  71. pos = best
  72. self.wasChanged = True
  73. return True
  74. def replaceMax(self, x):
  75. if self.heap == []:
  76. self.heap = [x]
  77. self.size = 1
  78. self.indices.add(x[0])
  79. self.wasChanged = True
  80. return True
  81. if x[0] in self.indices:
  82. return False
  83. if self.isGreaterThan(x, self.heap[0]):
  84. return False
  85. self.indices.remove((self.heap[0])[0])
  86. self.indices.add(x[0])
  87. self.heap[0] = x
  88. pos = 0
  89. size = len(self.heap)
  90. while pos < size:
  91. (left, right) = self.childPos(pos)
  92. if left >= size:
  93. break
  94. y = self.heap[left]
  95. if right >= size:
  96. if self.isGreaterThan(y, x):
  97. self.heap[pos] = y
  98. self.heap[left] = x
  99. break
  100. z = self.heap[right]
  101. (best, v) = (left, y) if self.isGreaterThan(y, z) else (right, z)
  102. if not self.isGreaterThan(v, x):
  103. break
  104. self.heap[pos] = v
  105. self.heap[best] = x
  106. pos = best
  107. self.wasChanged = True
  108. return True
  109. def getMax(self):
  110. if self.heap == []:
  111. return self.smalestValue
  112. return self.heap[0]
  113. def setMaxSize(self, maxSize):
  114. self.maxSize = maxSize
  115. while self.size > maxSize:
  116. self.removeMax()
  117. def toArray(self, mapFn=None):
  118. return list(self.indices)
  119. def toOrderedArray(self):
  120. c = self.copy()
  121. result = []
  122. while c.size > 0:
  123. result.append(c.getMax())
  124. c.removeMax()
  125. result.reverse()
  126. return result
  127. def length(self):
  128. return self.size