优先队列以比排序更小的代价维护顺序。二叉堆是实现优先队列的一种实现。二叉堆的最简单实现是数组。
# 基础
堆的基本操作:
- 插入
- 堆化,Sift Up,Sift Down
- 取出最值
使用数组表示的二叉堆的基本性质:
- 每个结点的左孩子为下标i的2倍:left child(i) = i * 2;每个结点的右孩子为下标i的2倍加1:right child(i) = i * 2 + 1
- 每个结点的父亲结点为下标的二分之一:parent(i) = i / 2,注意这里是整数除,2和3除以2都为1,大家可以验证一下
- 注意:这里是把下标为0的地方空出来了的,主要是为了方便理解,如果0不空出来只需要在计算的时候把i值往右偏移一个位置就行了(也就是加1)
# 实现
Go标准库提供了"container/heap"2封装了堆的基本操作。默认最小堆。
可以自定义struct,并重载method:
1 | |
重载Less为Greater逻辑即可获得最大堆。
# Heapify
# 实践
# 合并K个升序链表
优先队列合并,先顺序push所有链表最小值,在根据堆顶元素push下个值,时间复杂度O(kn * logk),空间复杂度O(k)
1 | |
其他方法:
- 遍历插入,时间复杂度为O(k2n),空间复杂度为O(1)
- 分治合并,时间复杂度为O(kn * logk),空间复杂度为O(logk)
# 数组中的第K个最大元素
构建优先队列,并删除k次
其他方法:
- 快排,取n-k个元素
1 | |
# 前K个高频元素
map统计,优先队列取前K个值。
1 | |
- [1] 数据结构与算法(4)——优先队列和堆 - 知乎
- [2] Package heap