数据结构与算法: 堆 优先队列 JavaScript语言描述

1 前言

我在很早之前的文章里,分享过有C语言手撸一个基于数组实现的最大堆,所以堆的基本实现思路和方法,不再赘述,详见:

数据与结构与算法: 堆 C语言描述

C语言可能受众小些,且略微不太好理解,今天就用JavaScript描述一个最小堆,其实是基于最小堆的优先队列,不过两者基本上么有什么太大的区别,无非堆是存最基础的数字,优先队列则储存的是一个结构体或者对象,有自己的key/value,有自己的属性。

2 与C语言版本的不同

  1. Js的数组本质还是对象,长度是可变的,而C语言的数组就是纯粹的数组,一旦确定下来,长度就不可变。故而在C版本中,我们需要维护size属性,不然不知道数组究竟使用到哪里了,这Js版本就不需要,直接读取data.length即可。
  2. 自带函数,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

算法之美
主要分享一些常见的,适合锻炼思维的入门级算法

code what u love & love what u code

212 声望
15 粉丝
0 条评论
推荐阅读
堆-优先队列进阶:TopK-3D接雨水-C-Js-Rust语言描述
在之前的文章里,我分享了Js版的堆实现和C语言版的堆实现, 理解的话,堆的实现其实并不难,以大顶堆为例,简单归纳就是插入时候,比节点小,就不断向下沉,让更大的上浮,直到最大的上浮到根节点。

tfzh阅读 1.1k

数据结构与算法-堆
在学习ScheduledThreadPoolExecutor时,发现该线程池使用的队列为DelayedWorkQueue,DelayedWorkQueue是一个基于堆结构实现的延时队列和优先级队列,为了搞明白DelayedWorkQueue的实现,本篇文章先对堆数据结构进...

半夏之沫阅读 1.2k

GO 实现优先队列
在php中提供了SplPriorityQueue来实现优先队列操作。在Go中,虽然没有直接提供优先队列的实现,不过通过标准库container/heap可以很方便的实现一个简单的优先队列。

tim_xiao阅读 581

学习算法必备的《程序员代码面试指南》免费领取啦!!
这是一本程序员代码面试宝典!书中对IT名企代码面试各类题目的最优解进行了总结,并提供了相关代码实现。针对当前程序员面试缺乏权威题目汇总这一痛点,本书选取将近200道真实出现过的经典代码面试题,帮助广大程...

Java架构师阅读 460

Python源码阅读:堆的入堆出堆方法实现
优先队列(priority queue)是一种特殊的队列,取出元素的顺序是按照元素的优先权(关键字)大小,而不是进入队列的顺序,堆就是一种优先队列的实现。堆一般是由数组实现的,逻辑上堆可以被看做一个完全二叉树(除底层...

ericlan77阅读 281

[C++STL教程]7.priority_queue优先队列入门学习!零基础都能听懂的教程
🎈 作者:Eriktse🎈 简介:19岁,211计算机在读,现役ACM银牌选手🏆力争以通俗易懂的方式讲解算法!❤️欢迎关注我,一起交流C++/Python算法。(优质好文持续更新中……)🚀🎈 个人博客:www.eriktse.com

Eriktse阅读 123

code what u love & love what u code

212 声望
15 粉丝
宣传栏