优先队列 - 看是 数组 实际 当成 完全二叉树
记住: 数组第i个元素,他的左节点的对应的元素下标是2 * i + 1,右节点对应的的元素下标是2 * i + 2
反之: 数组第i个元素,他的父节点是 Math.floor((i - 1) / 2)
直接上代码
大顶堆
class Heap {
constructor() {
this.data = []
}
// 堆的大小 === 数组的长度
size() {
return this.data.length
}
swap(i, j) {
const tmp = this.data[i]
this.data[i] = this.data[j]
this.data[j] = tmp
}
top() {
if (this.size() === 0) return
return this.data[0]
}
// 添加元素
push(val) {
this.data.push(val)
// 需要和父节点的值作对比
// val 节点的下标
let index = this.size() - 1
while (index > 0) {
// 记录父节点的下标
const parentIndex = Math.floor((index - 1) / 2)
if (this.data[index] > this.data[parentIndex]) {
// 交换两个位置的元素
this.swap(index, parentIndex)
// 然后再向上对比
index = parentIndex
}
}
}
// 弹出元素
pop() {
// 数组是空的时候
if (this.size() === 0) return
const lastOne = this.data.pop()
this.data[0] = lastOne
// 通过对比向下移动
// 单前位置
let index = 0
while(2 * i + 1 < this.size()) {
// 获取左节点和右节点下标
const leftIndex = 2 * i + 1
const rightIndex = 2 * i + 2
// 父节点和 左右节点中最大值进行交换
let findIndex = index
if (this.data[findIndex] < this.data[leftIndex]) {
findIndex = leftIndex
}
// 右节点可能不存在
if(rightIndex < this.size() && this.data[findIndex] < this.data[rightIndex]) {
findIndex = rightIndex
}
// 如果findIndex > index 则代表 单前节点的值不是最小的
if (findIndex > index) {
this.swap(index, findIndex)
index = findIndex
} else {
// index没有动 则是当前最大 停止循环
break
}
}
}
}
这样我们的大顶堆就可以了
小顶堆
父节点一定小于子节点
我们只需要传入一个连个元素对比的方法来判断下就可以了
整理后代码
function defaultCompare(a, b) {
return a > b
}
class Heap {
// 给定一个默认的比较方法
constructor(compare = defaultCompare) {
this.compare = compare
this.data = []
}
// 堆的大小 === 数组的长度
size() {
return this.data.length
}
swap(i, j) {
const tmp = this.data[i]
this.data[i] = this.data[j]
this.data[j] = tmp
}
top() {
if (this.size() === 0) return
return this.data[0]
}
// 添加元素
push(val) {
this.data.push(val)
// 需要和父节点的值作对比
// val 节点的下标
let index = this.size() - 1
while (index > 0) {
// 记录父节点的下标
const parentIndex = Math.floor((index - 1) / 2)
// 这里进行了比较
if (this.compare(this.data[index], this.data[parentIndex])) {
// 交换两个位置的元素
this.swap(index, parentIndex)
// 然后再向上对比
index = parentIndex
}
}
}
// 弹出元素
pop() {
// 数组是空的时候
if (this.size() === 0) return
const lastOne = this.data.pop()
this.data[0] = lastOne
// 通过对比向下移动
// 单前位置
let index = 0
while(2 * i + 1 < this.size()) {
// 获取左节点和右节点下标
const leftIndex = 2 * i + 1
const rightIndex = 2 * i + 2
// 父节点和 左右节点中最大值进行交换
let findIndex = index
// 这里进行了比较
if (!this.compare(this.data[findIndex], this.data[leftIndex])) {
findIndex = leftIndex
}
// 右节点可能不存在
if(rightIndex < this.size() && !this.compare(this.data[findIndex], this.data[rightIndex])) {
findIndex = rightIndex
}
// 如果findIndex > index 则代表 单前节点的值不是最小的
if (findIndex > index) {
this.swap(index, findIndex)
index = findIndex
} else {
// index没有动 则是当前最大 停止循环
break
}
}
}
}
总结
- 可以通过传入compare的比较两只方法来去做顶堆的处理