MaxHeap.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  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. x = self.heap[0]
  44. self.indices.remove(x[0])
  45. self.heap[0] = self.heap[-1]
  46. self.heap = self.heap[:-1]
  47. self.size -= 1
  48. x = self.heap[0]
  49. pos = 0
  50. size = self.size
  51. while pos < size:
  52. (left, right) = self.childPos(pos)
  53. if left >= size:
  54. break
  55. y = self.heap[left]
  56. if right >= size:
  57. if self.isGreaterThan(y, x):
  58. self.heap[pos] = y
  59. self.heap[left] = x
  60. break
  61. z = self.heap[right]
  62. (best, v) = (left, y) if self.isGreaterThan(y, z) else (right, z)
  63. if not self.isGreaterThan(v, x):
  64. break
  65. self.heap[pos] = v
  66. self.heap[best] = x
  67. pos = best
  68. self.wasChanged = True
  69. return True
  70. def replaceMax(self, x):
  71. if self.heap == []:
  72. self.heap = [x]
  73. self.size = 1
  74. self.indices.add(x[0])
  75. self.wasChanged = True
  76. return True
  77. if x[0] in self.indices:
  78. return False
  79. if self.isGreaterThan(x, self.heap[0]):
  80. return False
  81. self.indices.remove((self.heap[0])[0])
  82. self.indices.add(x[0])
  83. self.heap[0] = x
  84. pos = 0
  85. size = len(self.heap)
  86. while pos < size:
  87. (left, right) = self.childPos(pos)
  88. if left >= size:
  89. break
  90. y = self.heap[left]
  91. if right >= size:
  92. if self.isGreaterThan(y, x):
  93. self.heap[pos] = y
  94. self.heap[left] = x
  95. break
  96. z = self.heap[right]
  97. (best, v) = (left, y) if self.isGreaterThan(y, z) else (right, z)
  98. if not self.isGreaterThan(v, x):
  99. break
  100. self.heap[pos] = v
  101. self.heap[best] = x
  102. pos = best
  103. self.wasChanged = True
  104. return True
  105. def getMax(self):
  106. if self.heap == []:
  107. return self.smalestValue
  108. return self.heap[0]
  109. def setMaxSize(self, maxSize):
  110. self.maxSize = maxSize
  111. while self.size > maxSize:
  112. self.removeMax()
  113. def toArray(self, mapFn=None):
  114. return list(self.indices)
  115. def toOrderedArray(self):
  116. c = self.copy()
  117. result = []
  118. while c.size > 0:
  119. result.append(c.getMax())
  120. c.removeMax()
  121. return result.reverse()
  122. def length(self):
  123. return self.size