最大堆
堆的基本存储结构是数组
插入删除的具体思路,
最大堆的前提是二叉搜索树,插入的思路是,先将数据插入到元素最末尾,然后依次与其父节点进行比较,如果比父节点大,则将父节点与其交换位置,直到父节点小于等于插入的数。
删除的思路,
先弹出最大的节点,然后将最后一个节点放到最大堆的堆顶,依次与子节点进行比较,与子节点中最大值进行比较,如果大于子节点的最大值,则退出循环,反之则与子节点中最大值进行交换,并继续与子节点进行比较。
JavaScript
class MaxHeap {
constructor() {
this.item = []
this.item[0] = 1000000007
}
/**
* @param {int} value 插入的值
*/
push = (value) => {
let item = this.item
item.push(value)
let k = this.size()
while (item[Math.floor(k / 2)] < value) {
item[k] = item[Math.floor(k / 2)]
k = Math.floor(k / 2)
}
item[k] = value
}
/**
* @return 去掉最大值,并返回值
*/
pop = () => {
if (this.isEmpty()) return Error('堆为空')
let item = this.item
let i, k, maxItem = item[1]
let temp = item.pop()
/*从根节点开始遍历*/
for (i = 1; i * 2 <= this.size(); i = k) {
k = i * 2
if (k !== this.size()) {
/* k指向较大的节点*/
k = item[k] < item[k + 1] ? k + 1 : k
}
if (temp >= item[k]) break
else item[i] = item[k]
}
item[i] = temp
return maxItem
}
/**
* @return 返回值
*/
get = () => {
return this.item[1]
}
/**
* @return 返回堆中数的大小
*/
size = () => {
return this.item.length - 1
}
/**
* @return {boolean} 返回堆是否为空
*/
isEmpty = () => {
return this.item.length == 1 ? true : false
}
}
最小堆
思路与最大堆一样
JavaScript
class MinHeap {
constructor() {
this.item = []
this.item[0] = -1000000007
}
push = (value) => {
let item = this.item
item.push(value)
let k = this.size()
while (value < item[Math.floor(k / 2)]) {
item[k] = item[Math.floor(k / 2)]
k = Math.floor(k / 2)
}
item[k] = value
}
pop = () => {
if (this.isEmpty()) return Error('MinHeap has null')
let item = this.item
let k, i,minItem = item[1]
let temp = item.pop()
for (i = 1; i * 2 <= this.size(); i = k) {
k = i * 2
if (k !== this.size()) k = item[k] < item[k + 1] ? k : k + 1
if (temp <= item[k]) break
else item[i] = item[k]
}
item[i] = temp
return minItem
}
get = () => {
return this.item[1]
}
size = () => {
return this.item.length - 1
}
isEmpty = () => {
return this.size() === 0
}
}
自定义堆
class Heap {
/**
* 传入的最大最小值,如果是最小堆,传入-1000000007,最大值传入1000000007,
* 如果是对象则传{value:-1000000007}
* @param {number} key
*/
constructor(key,func) {
this.item = []
this.item[0] = key?? -1000000007
if (typeof func === 'function') this.compare = func
}
push = (value) => {
let compare = this.compare
let item = this.item
item.push(value)
let k = this.size()
while (compare(value, item[Math.floor(k / 2)])<0) {
item[k] = item[Math.floor(k / 2)]
k = Math.floor(k / 2)
}
item[k] = value
}
pop = () => {
if (this.isEmpty()) return Error('MinHeap has null')
let item = this.item
let k, i, minItem = item[1]
let temp = item.pop()
let compare = this.compare
for (i = 1; i * 2 <= this.size(); i = k) {
k = i * 2
if (k !== this.size()) k = compare(item[k], item[k + 1]) <0 ? k : k + 1
if (compare(temp, item[k]) <= 0) break
else item[i] = item[k]
}
item[i] = temp
return minItem
}
get = () => {
return this.item[1]
}
size = () => {
return this.item.length - 1
}
/**
* 比较函数,如果是最小堆,返回a-b,如果是最大堆,返回b-a
*/
compare = (a, b) => {
return b-a
}
isEmpty = () => {
return this.size() === 0
}
}
使用举例
//最小堆
let heap = new Heap(-1000000007,(a,b)=>a-b)
for(let i=10;i>0;i--){
heap.push(i)
}
for(let i=0;i<10;i++){
console.log(heap.pop())
}
console.log(1);
//最大堆
let heap = new Heap(1000000007,(a,b)=>a-b)
for(let i=10;i>0;i--){
heap.push(i)
}
for(let i=0;i<10;i++){
console.log(heap.pop())
}
console.log(1);
Q.E.D.