D
AI
学习工作台
数据结构2026-05-221 分钟阅读

堆与优先队列

大根堆、Top K、合并 K 路与中位数

优先队列Top K面试记笔记标记疑惑

堆结构

用数组 heap[0..n-1] 存储完全二叉树:parent=(i-1)//2left=2i+1right=2i+2

  • 插入:尾部追加,sift_up
  • 删除堆顶:末尾换到顶再 sift_down
  • Pythonheapq 为小根堆;大根堆存负值或自定义比较。
import heapq

小根堆

h = [] heapq.heappush(h, 3) heapq.heappush(h, 1) x = heapq.heappop(h) # 1

Top K 最大:维护大小 k 的小根堆

def top_k(nums, k): heap = nums[:k] heapq.heapify(heap) for x in nums[k:]: if x > heap[0]: heapq.heapreplace(heap, x) return heap

优先队列抽象

优先级出队,底层即堆。Dijkstra、Prim、任务调度、合并 K 个有序链表都用小根堆按当前最小边/距离/节点值弹出。

合并 K 路有序链表

def merge_k_lists(lists):
    heap = []
    for i, node in enumerate(lists):
        if node:
            heapq.heappush(heap, (node.val, i, node))
    dummy = cur = ListNode(0)
    while heap:
        _, i, node = heapq.heappop(heap)
        cur.next = node
        cur = cur.next
        if node.next:
            heapq.heappush(heap, (node.next.val, i, node.next))
    return dummy.next

数据流中位数

对顶堆:左侧大根堆存较小一半,右侧小根堆存较大一半,保持 |len(left)-len(right)| <= 1,中位数为堆顶或两堆顶平均。插入时 O(log n)。

与其他结构对比

| 需求 | 结构 | |---|---| | 全局最值动态 | 堆 | | 有序集合全序 | 平衡 BST / TreeMap | | 仅最值一次 | 扫描 O(n) |

练习:215、347、23、295、703。面试写 heapq 时注明小根堆语义及 tuple 比较规则(避免节点对象不可比)。

知识卡片

问题

堆的结构性与堆序性?

点击翻转查看答案

答案

结构性:完全二叉树用数组存;堆序性:父节点不大于(小根堆)或不小于(大根堆)子节点,根为最值。

问题

建堆时间复杂度?

点击翻转查看答案

答案

从最后一个非叶节点向下 sift-down,整体 O(n);单次插入/删除 O(log n)。

问题

求 Top K 大元素用多大堆?

点击翻转查看答案

答案

维护大小为 K 的小根堆,堆顶是 K 大中最小的;新元素更大则替换堆顶,最终堆内为 Top K。