什么是优先队列
优先队列也是一种队列,只不过不同的是,优先队列的出队顺序是按照优先级来的。
优先队列(ADT, Abstract Data Type)是一种数据结构, 支持插入和删除最小/大值操作(返回并删除最小/大元素)。
对于最小健值元素拥有最高的优先队列, 称之为升序优先队列。
同理, 对于最大健值元素拥有最高的优先队列,称之为降序优先队列。
解决什么问题
需要找到元素集合中的最小或最大元素。
优先队列ADT操作
主要操作
- 插入
- 删除
- 获取
辅助操作
- 第k小/大
- 大小
- 堆排列
优先队列的应用
- 数据压缩:赫夫曼编码算法
- 最短路径算法:Dijkstra算法
- 最小生成树算法:Prim算法
- 事件驱动仿真:顾客排队算法
- 选择问题:查找第k个最小元素 拜托,面试别再问我TopK了!!!
练习题集合
- 剑指 Offer II 059. 数据流的第 K 大数值
- 703. 数据流中的第 K 大元素
- 剑指 Offer 40. 最小的k个数
- 1337. 矩阵中战斗力最弱的 K 行
- 1464. 数组中两元素的最大乘积
- 2099. 找到和最大的长度为 K 的子序列
- LCP 33. 蓄水
- 1046. 最后一块石头的重量
- 506. 相对名次
- 1834. 单线程 CPU
堆(大根堆/小根堆)
大根堆:父节点的值比每一个子节点的值都要大。
同理, 小根堆:父节点的值比每一个子节点的值都要小。
class MinHeap {
constructor(data = []) {
this.data = data;
this.comparator = (a, b) => a - b;
this.heapify();
}
// 堆化
heapify() {
if (this.size() < 2) return;
for (let i = 1; i < this.size(); i++) {
this.bubbleUp(i);
}
}
peek() {
if (this.size() === 0) return null;
return this.data[0];
}
offer(value) {
this.data.push(value);
this.bubbleUp(this.size() - 1);
}
poll() {
if (this.size() === 0) {
return null;
}
const result = this.data[0];
const last = this.data.pop();
if (this.size() !== 0) {
this.data[0] = last;
this.bubbleDown(0);
}
return result;
}
bubbleUp(index) {
while (index > 0) {
const parentIndex = (index - 1) >> 1;
if (this.comparator(this.data[index], this.data[parentIndex]) < 0) {
this.swap(index, parentIndex);
index = parentIndex;
} else {
break;
}
}
}
bubbleDown(index) {
const lastIndex = this.size() - 1;
while (true) {
const leftIndex = index * 2 + 1;
const rightIndex = index * 2 + 2;
let findIndex = index;
if (
leftIndex <= lastIndex &&
this.comparator(this.data[leftIndex], this.data[findIndex]) < 0
) {
findIndex = leftIndex;
}
if (
rightIndex <= lastIndex &&
this.comparator(this.data[rightIndex], this.data[findIndex]) < 0
) {
findIndex = rightIndex;
}
if (index !== findIndex) {
this.swap(index, findIndex);
index = findIndex;
} else {
break;
}
}
}
swap(index1, index2) {
[this.data[index1], this.data[index2]] = [this.data[index2], this.data[index1]];
}
size() {
return this.data.length;
}
}
第k个最小元素
var KthLargest = function(k, nums) {
this.k = k;
this.heap = new MinHeap();
for (let num of nums) {
this.add(num);
}
};
KthLargest.prototype.add = function(val) {
this.heap.offer(val);
if (this.heap.size() > this.k) {
this.heap.poll();
}
return this.heap.peek();
};