|
| 1 | +# python3 |
| 2 | +class MinHeap: |
| 3 | + def __init__(self): |
| 4 | + """ |
| 5 | + 这里提供一个最小堆实现。如果面试不让用内置的堆非让你自己实现的话,考虑用这个简版的最小堆实现。 |
| 6 | + 一般只需要实现 heqppop,heappush 两个操作就可以应付面试题了 |
| 7 | + parent: (i-1)//2。注意这么写 int((n-1)/2), python3 (n-1)//2当n=0结果是-1而不是0 |
| 8 | + left: 2*i+1 |
| 9 | + right: 2*i+2 |
| 10 | + 参考: |
| 11 | + https://favtutor.com/blogs/heap-in-python |
| 12 | + https://runestone.academy/ns/books/published/pythonds/Trees/BinaryHeapImplementation.html |
| 13 | + https://www.askpython.com/python/examples/min-heap |
| 14 | + """ |
| 15 | + self.pq = [] |
| 16 | + |
| 17 | + def min_heapify(self, nums, k): |
| 18 | + """递归调用,维持最小堆特性""" |
| 19 | + l = 2*k+1 # 左节点位置 |
| 20 | + r = 2*k+2 # 右节点 |
| 21 | + if l < len(nums) and nums[l] < nums[k]: |
| 22 | + smallest = l |
| 23 | + else: |
| 24 | + smallest = k |
| 25 | + if r < len(nums) and nums[r] < nums[smallest]: |
| 26 | + smallest = r |
| 27 | + if smallest != k: |
| 28 | + nums[k], nums[smallest] = nums[smallest], nums[k] |
| 29 | + self.min_heapify(nums, smallest) |
| 30 | + |
| 31 | + def heappush(self, num): |
| 32 | + """列表最后就加入一个元素,之后不断循环调用维持堆特性""" |
| 33 | + self.pq.append(num) |
| 34 | + n = len(self.pq) - 1 |
| 35 | + # 注意必须加上n>0。因为 python3 (n-1)//2 当n==0 的时候结果是-1而不是0! |
| 36 | + while n > 0 and self.pq[n] < self.pq[(n-1)//2]: # parent 交换 |
| 37 | + self.pq[n], self.pq[(n-1)//2] = self.pq[(n-1)//2], self.pq[n] # swap |
| 38 | + n = (n-1)//2 |
| 39 | + |
| 40 | + def heqppop(self): # 取 pq[0],之后和pq最后一个元素pq[-1]交换之后调用 min_heapify(0) |
| 41 | + minval = self.pq[0] |
| 42 | + last = self.pq[-1] |
| 43 | + self.pq[0] = last |
| 44 | + self.min_heapify(self.pq, 0) |
| 45 | + self.pq.pop() |
| 46 | + return minval |
| 47 | + |
| 48 | + def heapify(self, nums): |
| 49 | + n = int((len(nums)//2)-1) |
| 50 | + for k in range(n, -1, -1): |
| 51 | + self.min_heapify(nums, k) |
| 52 | + |
| 53 | + |
| 54 | +def test_MinHeqp(): |
| 55 | + import random |
| 56 | + l = list(range(1, 9)) |
| 57 | + random.shuffle(l) |
| 58 | + pq = MinHeap() |
| 59 | + for num in l: |
| 60 | + pq.heappush(num) |
| 61 | + res = [] |
| 62 | + for _ in range(len(l)): |
| 63 | + res.append(pq.heqppop()) # 利用 heqppop,heqppush 实现堆排序 |
| 64 | + |
| 65 | + def issorted(l): return all(l[i] <= l[i+1] for i in range(len(l) - 1)) |
| 66 | + assert issorted(res) |
0 commit comments