堆
概念:1.堆是一种特殊的完全二叉树
2.所有的节点都大于等于(最大堆)或小于等于(最小堆)它的子节点
特点:
1.js中通常使用数组表示堆
2.左侧子节点的位置是: 2*index + 1
3.右侧子节点的位置是: 2*index + 2
4.父节点位置是(index-1)/ 2
最小堆
class MinHeap {
constructor() {
this.heap = [];
}
swap(index1, index2) {
const temp = this.heap[index1];
this.heap[index1] = this.heap[index2];
this.heap[index2] = temp;
}
// 获取父节点
getParentIndex(index) {
return (index - 1) >> 1;
}
// 获取左节点
getLeftIndex(index) {
return (index << 1) + 1
}
// 获取右节点
getRightIndex(index) {
return (index << 1) + 2
}
// 上移
shiftUp(index) {
if (index == 0) return;
const parentIndex = this.getParentIndex(index);
if (this.heap[parentIndex] > this.heap[index]) { // 父节点大于子节点
this.swap(parentIndex, index);
this.shiftUp(parentIndex);
}
}
// 下移
shiftDown(index) {
const leftIndex = this.getLeftIndex(index);
const rightIndex = this.getRightIndex(index);
if (this.heap[leftIndex] < this.heap[index]) {
this.swap(leftIndex, index);
this.shiftDown(leftIndex);
}
if (this.heap[rightIndex] < this.heap[index]) {
this.swap(rightIndex, index);
this.shiftDown(rightIndex);
}
}
// 插入
insert(value) {
this.heap.push(value);
this.shiftUp(this.heap.length - 1);
}
// 删除堆顶
pop() {
this.heap[0] = this.heap.pop();
this.shiftDown(0);
}
// 获取堆顶
peek() {
return this.heap[0];
}
// 获取堆大小
size() {
return this.heap.length;
}
}
最大堆
class MaxHeap {
constructor() {
this.h = [];
}
swap(parentIndex, childrenIndex) {
[this.h[parentIndex], this.h[childrenIndex]] = [this.h[childrenIndex], this.h[parentIndex]];
}
getParentIndex(childrenIndex) {
return (childrenIndex - 1) >> 1;
}
upshift(index) {
if (index === 0) return;
let parentIndex = this.getParentIndex(index);
// 小于区别最小堆
if (this.h[parentIndex] < this.h[index]) {
this.swap(parentIndex, index);
this.upshift(parentIndex);
}
}
getChildrenLeftIndex(parentIndex) {
return (parentIndex << 1) + 1;
}
getChildrenRightIndex(parentIndex) {
return (parentIndex << 1) + 2
}
downshift(index) {
const leftIndex = this.getChildrenLeftIndex(index);
const rightIndex = this.getChildrenRightIndex(index);
// 大于区别最小堆
if (this.h[leftIndex] > this.h[index]) {
this.swap(leftIndex, index);
this.downshift(leftIndex);
}
// 大于区别最小堆
if (this.h[rightIndex] > this.h[index]) {
this.swap(rightIndex, index)
this.downshift(rightIndex);
}
}
insert(val) {
this.h.push(val);
this.upshift(this.h.length - 1);
}
peek() {
return this.h[0];
}
size() {
return this.h.length;
}
pop() {
this.h[0] = this.h.pop();
this.downshift(0);
}
}