(二叉)堆的定义
(二叉)堆是一个数组,可以被看成一个近似的完全二叉树。
class MaxHeap:def __init__(self, nums: List[int]):self.size = len(nums)# 堆数组索引从1开始,方便left, right和parent的计算self.arr = [0 for _ in range(self.size + 1)]def _left(self, i):return 2 * idef _right(self, i):return 2 * i + 1def _parent(self, i):return i // 2# 假定arr[i]的以left(i)和right(i)为根的二叉树# 都是最大堆def max_heapify(self, i):size = self.sizel, r = self._left(i), self._right(i)if l <= size and self.arr[l] > self.arr[i]:largest = lelse:largest = iif r <= size and self.arr[r] > self.arr[largest]:largest = rif largest != i:self.arr[i], self.arr[largest] = self.arr[largest], self.arr[i]# 交换过后可能不是最大堆,所以得维护堆的性质self.max_heapify(largest)
堆排序
步骤:
- 用给定的数组构建一个最大堆
- 将最大堆的根节点移动到末尾
- 除去末尾的结点并维护最大堆的性质
重复此过程 ```python def build_max_heap(nums: List[int]) -> MaxHeap: heap = MaxHeap(nums) for i in range(len(nums)):
heap.arr[i+1] = nums[i]
默认叶节点是符合最大堆的性质
for i in range(heap.size // 2, 0, -1):
heap.max_heapify(i)
return heap
def heap_sort(nums):
# 也可以原地排序,不过得修改left(i),right(i)和parent(i)heap = build_max_heap(nums)for i in range(heap.size, 1, -1):heap.arr[1], heap.arr[i] = heap.arr[i], heap.arr[1]heap.size -= 1heap.max_heapify(1)ret = heap.arr[1:]return ret
性能分析
时间复杂度:
max_heapify():(
为堆的高度)
build_max_heap():heap_sort():
