数据结构与算法: 堆 优先队列 JavaScript语言描述
1 前言
我在很早之前的文章里,分享过有C
语言手撸一个基于数组实现的最大堆,所以堆的基本实现思路和方法,不再赘述,详见:
C
语言可能受众小些,且略微不太好理解,今天就用JavaScript
描述一个最小堆,其实是基于最小堆的优先队列,不过两者基本上么有什么太大的区别,无非堆是存最基础的数字,优先队列则储存的是一个结构体或者对象,有自己的key/value
,有自己的属性。
2 与C
语言版本的不同
Js
的数组本质还是对象,长度是可变的,而C
语言的数组就是纯粹的数组,一旦确定下来,长度就不可变。故而在C
版本中,我们需要维护size
属性,不然不知道数组究竟使用到哪里了,这Js
版本就不需要,直接读取data.length
即可。- 自带函数,
Js
这种高级语言,自带很多函数,比如我们使用pop()
函数就直接弹出了数组的末尾,其长度自动减一,而C
语言版本显然没有这个功能
3 代码
var Heap = function () {
this.data = []
this.insert = (obj) => {
let i = this.data.length
for (; i > 0 && this.data[Math.floor((i - 1) / 2)].val >= obj.val; i = Math.floor((i - 1) / 2)) {
if (i < 1) {
break
}
this.data[i] = this.data[Math.floor((i - 1) / 2)]
}
this.data[i] = obj
}
this.pop = () => {
if (this.data.length == 0) {
return null
}
if (this.data.length == 1) {
return this.data.pop()
}
let top = this.data[0]
this.data[0] = this.data.pop()
let i = 0
while (2 * i + 1 < this.data.length) {
if (2 * i + 2 < this.data.length) {
if (this.data[2 * i + 2].val < this.data[i].val || this.data[2 * i + 1].val < this.data[i].val) {
if (this.data[2 * i + 2].val < this.data[2 * i + 1].val) {
this.swap(i, 2 * i + 2)
i = 2 * i + 2
} else {
this.swap(i, 2 * i + 1)
i = 2 * i + 1
}
} else {
break
}
} else {
if (this.data[2 * i + 1].val < this.data[i].val) {
this.swap(i, 2 * i + 1)
i = 2 * i + 1
} else {
break
}
}
}
return top
}
this.swap = (i, j) => {
let tmp = this.data[j]
this.data[j] = this.data[i]
this.data[i] = tmp
}
};
4 实际测试
测试代码如下
let obj = new Heap()
obj.insert({ val: 19 })
obj.insert({ val: 10 })
obj.insert({ val: 11 })
obj.insert({ val: 19 })
obj.insert({ val: 100 })
obj.insert({ val: 18 })
obj.insert({ val: 200 })
obj.insert({ val: 18 })
console.log(obj)
let len = obj.data.length
for (let index = 0; index < len; index++) {
console.log(obj.pop())
}
以下为打印内容:
[Running] node "d:\Test\heap.js"
Heap {
data: [
{ val: 10 },
{ val: 18 },
{ val: 11 },
{ val: 19 },
{ val: 100 },
{ val: 18 },
{ val: 200 },
{ val: 19 }
],
insert: [Function (anonymous)],
pop: [Function (anonymous)],
swap: [Function (anonymous)]
}
{ val: 10 }
{ val: 11 }
{ val: 18 }
{ val: 18 }
{ val: 19 }
{ val: 19 }
{ val: 100 }
{ val: 200 }
[Done] exited with code=0 in 0.089 seconds
算法之美
主要分享一些常见的,适合锻炼思维的入门级算法
推荐阅读
堆-优先队列进阶:TopK-3D接雨水-C-Js-Rust语言描述
在之前的文章里,我分享了Js版的堆实现和C语言版的堆实现, 理解的话,堆的实现其实并不难,以大顶堆为例,简单归纳就是插入时候,比节点小,就不断向下沉,让更大的上浮,直到最大的上浮到根节点。
tfzh阅读 1.3k
常见排序算法及复杂度
大O加上()的形式,里面其实包裹的是一个函数f(),O(f()),指明某个算法的 “耗时/耗空间”与“数据增长量”之间的关系。其中的 n代表输入数据的量。
KerryWu阅读 321
[C++STL教程]7.priority_queue优先队列入门学习!零基础都能听懂的教程
🎈 作者:Eriktse🎈 简介:19岁,211计算机在读,现役ACM银牌选手🏆力争以通俗易懂的方式讲解算法!❤️欢迎关注我,一起交流C++/Python算法。(优质好文持续更新中……)🚀🎈 个人博客:www.eriktse.com
Eriktse阅读 275
时间复杂度 - 记录笔记
时间复杂度分析概念 {代码...} 思路 {代码...} 公式 {代码...} 常用的时间复杂度比较关系 {代码...} 例题举例求以下算法的时间复杂度 {代码...} 一:找出基本操作,确定规模n {代码...} 二:计算n的函数f(n) {代...
王彬阅读 188
平衡树之 AVL 树
由于二叉树的结构特性,将数据存储到二叉搜索树中,其时间复杂度可以从存储在线性结构的的 O(N) 变成 O(log2 N) 。但这只是在理想的情况下的效率(如图1 左),在实际的操作,树的结构会不断的变换,极端的情况下...
daydream
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。