定场诗

马瘦毛长蹄子肥,儿子偷爹不算贼,瞎大爷娶个瞎大奶奶,老两口过了多半辈,谁也没看见谁!

前言

本章为重读《学习JavaScript数据结构与算法-第三版》的系列文章,主要讲述队列数据结构、双端队列数据结构以及队列相关应用。

队列

队列是遵循先进先出(FIFO)原则的一组有序的项。队列在尾部添加元素,并从顶部移除元素。最新添加的元素必须排在队列的末尾。现实中常见的队列就是排队,计算机科学中,常见的例子是打印队列,如文档按顺序打印,第一个发送到打印队列的文档优先被打印。

实现队列

/**
* class Queue 队列类
* 特点:先进先出
*/
class Queue {
construcor () {
// 存储数据
this.items = {}
// 队列头部元素索引
this.lowestCount = 0
// 队列尾部元素索引
this.count = 0
} /**
* enqueue() 添加元素到队列 - 先进先出
* @param {*} element 添加到队列的元素
*/
enqueue (elemenet) {
this.items[this.count] = element
this.count++
} /**
* dequeue() 移除队列头部元素 - 先进先出
* @returns {*} result 返回头部元素
*/
dequeue () {
if (this.isEmpty()) {
return undefined
}
let result = this.items[this.lowestCount]
delete this.items[this.lowestCount]
this.lowestCount++
return result
} /**
* peek() 返回队列头部元素
* @returns {*}
*/
peek () {
if (this.isEmpty()) {
return undefined
}
return this.items[this.lowestCount]
} /**
* isEmpty() 判断队列是否为空
* @returns {Boolean}
*/
isEmpty () {
return this.count === this.lowestCount
} /**
* size() 队列长度
* @returns {Number}
*/
size () {
return this.count - this.lowestCount
} /**
* clear() 清空队列
*/
clear () {
this.items = {}
this.count = 0
this.lowestCount = 0
} /**
* toString() 返回队列的字符串结构
* @returns {String}
*/
toString () {
if (this.isEmpty()) {
return ''
}
let queueStr = `${this.items[this.lowestCount]}`
for (let i = this.lowestCount + 1; i < this.count; i++) {
queueStr = `${queueStr},${this.items[i]}`
}
return queueStr
}
}

使用队列

// 实例化队列
const queue = new Queue() // 判断队列是否为空
console.log(queue.isEmpty()) // true // 向队列中添加元素
queue.enqueue('John')
queue.enqueue('Jack') console.log(queue.toString()) // John,Jack queue.enqueue('Camila') console.log(queue.toString()) // John,Jack console.log(queue.size()) // 3 console.log(queue.isEmpty()) // false

以上操作示意图:

console.log(queue.dequeue()) // John
console.log(queue.dequeue()) // Jack
console.log(queue.toString()) // Camila

以上操作示意图

双端队列

双端队列是一种允许我们同时从前端和后端添加和移除元素的特殊队列。在计算机科学中双端队列常见应用是存储一系列的撤销操作。

  1. 当用户在软件中进行了操作时,该操作从尾部进入双端队列;
  2. 当用户点击撤销按钮时,从双端队列的尾部移除;
  3. 当队列中的操作达到预定义的一定数量后,最先存入的操作会被移除(头部移除)

双端队列同时遵守了先进先出和后进先出的原则

实现双端队列

/**
* class Deque 双端队列
* 特点:支持先进先出、后进先出
*/
class Deque {
constructor () {
this.items = {}
this.count = 0
this.lowestCount = 0
} /**
* addFront() 从头部插入
* @param {*} element 待插入队首的元素
*/
addFront (element) {
this.lowestCount--
this.items[this.lowestCount] = element
} /**
* addBack() 从尾部插入
* @param {*} element 待插入队尾的元素
*/
addBack (element) {
this.items[this.count] = element
this.count++
} /**
* removeFront() 队首移除元素
* @returns {*}
*/
removeFront () {
if (this.isEmpty()) {
return undefined
}
let result = this.items[this.lowestCount]
delete this.items[this.lowestCount]
this.lowestCount++
return result
} /**
* removeBack() 队尾移除元素
* @returns {*}
*/
removeBack () {
if (this.isEmpty()) {
return undefined
}
let result = this.items[this.count -1]
delete this.items[this.count - 1]
this.count--
return result
} /**
* isEmpty() 判断是否为空
* @returns {Boolean} 是否为空
*/
isEmpty () {
return this.count === this.lowestCount
} /**
* size() 返回队列的长度
* @returns {Number} 队列的长度
*/
size () {
return this.count - this.lowestCount
} /**
* clear() 清空队列
*/
clear () {
this.items = {}
this.count = 0
this.lowestCount = 0
} /**
* peekFront() 获取队首元素
* @returns {*}
*/
peekFront () {
if (this.isEmpty()) {
return undefined
}
return this.items[this.lowestCount]
} /**
* peekBack() 获取队尾元素
* @returns {*}
*/
peekBack () {
if (this.isEmpty()) {
return undefined
}
return this.items[this.count - 1]
} /**
* toString() 展示字符串形式
* @returns {*}
*/
toString () {
if (this.isEmpty()) {
return ''
}
let str = `${this.items[this.lowestCount]}`
for (let i = this.lowestCount + 1; i < this.count; i++) {
str = `${str},${this.items[i]}`
}
return str
}
}

使用双端队列

const deque = new Deque()

console.log(deque.isEmpty()) // true

deque.addFront('宋江')
deque.addFront('晁盖')
deque.addBack('吴用') console.log(deque.size()) // 3
console.log(deque.toString()) // 晁盖,宋江,吴用 console.log(deque.removeFront()) // 晁盖
console.log(deque.removeBack()) // 吴用 console.log(deque.toString()) // 宋江
console.log(deque.size()) // 1

实战应用

循环队列 - 模拟击鼓传花游戏

规则:

  1. 使用队列模拟击鼓传花
  2. 当执行一定的约定次数(每次都随机一个数)时,花在谁手里,谁被淘汰
  3. 重复执行游戏,直到剩下最后一人,为胜利者
/**
* hotPotato() 模拟击鼓传花游戏
* @param {Array} elementList 需传入的参与游戏的人员列表
* @returns {Object} 返回信息:淘汰者和胜利者
*/
function hotPotato (elementList) {
// 实例化队列,将元素放入队列
let queue = new Queue()
elementList.forEach((value) => {
queue.enqueue(value)
}) // 淘汰的人
let elimitatedList = [] // 开始游戏,直到队列中剩余1人
while (queue.size() > 1) {
// 为了让游戏更加有意思,每次停止的位置进行随机处理
for (let i = 0; i < Math.floor(Math.random() * 10); i++) {
// 取出头部第一个元素,然后执行插入
queue.enqueue(queue.dequeue())
}
// 此时拥有花的人,淘汰
elimitatedList.push(queue.dequeue())
} // 返回
return {
elimitatedList,
winner: queue.dequeue()
}
} let elementList = [
'孙悟空',
'唐僧',
'如来佛祖',
'玉帝',
'王母'
] // 调用函数,传入elementList,同时约定第6次时,拥有花的小伙伴被淘汰...
let result = hotPotato(elementList, 6)
console.log(result) result.elimitatedList.forEach((name) => {
console.log(`${name}被淘汰了...`)
}) console.log(`${result.winner}胜利了...`)

以上代码运行效果 -- 展示其中一次的执行结果

{ elimitatedList: [ '唐僧', '王母', '孙悟空', '如来佛祖' ], winner: '玉帝' }

唐僧被淘汰了...

王母被淘汰了...

孙悟空被淘汰了...

如来佛祖被淘汰了...

玉帝胜利了...

回文检查器

什么是回文?

回文是正反都能读通的单词、词组、数或一系列字符的序列,例如:aba、madam

那如何实现回文检查器呢?

1. 使用反转排列字符串与原字符串进行比较

/**
* palindromeChecker() 回文检查器
* @param {String} str 待检查的字符串
* @returns {Boolean}
*/
function palindromeChecker (str) {
// 检测是否是合法字符串
if (str === undefined || str === null || (str !== null && str.length === 0)) {
return false
}
return str.split('').reverse().join('') === str
} let str = 'aba'
console.log(palindromeChecker(str)) // true

2. 使用数据结构-栈实现回文检查器

/**
* palindromeChecker() 回文检查器
* @param {String} str 待检查的字符串
* @returns {Boolean}
*/
function palindromeChecker (str) {
// 检测是否是合法字符串
if (str === undefined || str === null || (str !== null && str.length === 0)) {
return false
}
let stack = new Stack()
// 分割字符串
for (let i = 0; i < str.length; i++) {
stack.push(str[i])
} let reverseStr = ''
while (!stack.isEmpty()) {
reverseStr += stack.pop()
}
return str === reverseStr
} let str = 'aba'
console.log(palindromeChecker(str)) // true

此处栈 class Stack的实现,请参考上一篇文章:重读《学习JavaScript数据结构与算法-第三版》- 第4章 栈

3. 使用双端队列实现回文检查器

/**
* palindromeChecker() 回文检查器
* @param {String} str 待检查的字符串
* @returns {Boolean}
*/
function palindromeChecker (str) {
// 检测是否是合法字符串
if (str === undefined || str === null || (str !== null && str.length === 0)) {
return false
} let deque = new Deque() for (let i = 0; i < str.length; i++) {
deque.addBack(str[i])
} // 设置是否是回文的标记
let isEqual = true
while (deque.size() > 1 && isEqual) {
// 取出收尾进行比较
let front = deque.peekFront()
let back = deque.peekBack() if (front !== back) {
isEqual = false
}
} return isEqual
} let str = 'abc'
console.log(palindromeChecker(str)) // false
str = 'aba'
console.log(palindromeChecker(str)) // true

后记

以上就是胡哥今天给大家分享的内容,喜欢的小伙伴记得收藏转发、点击右下角按钮在看,推荐给更多小伙伴呦,欢迎多多留言交流...

胡哥有话说,一个有技术,有情怀的胡哥!京东开放平台首席前端攻城狮。与你一起聊聊大前端,分享前端系统架构,框架实现原理,最新最高效的技术实践!

长按扫码关注,更帅更漂亮呦!关注胡哥有话说公众号,可与胡哥继续深入交流呦!

重读《学习JavaScript数据结构与算法-第三版》- 第5章 队列的更多相关文章

  1. 重读《学习JavaScript数据结构与算法-第三版》- 第4章 栈

    定场诗 金山竹影几千秋,云索高飞水自流: 万里长江飘玉带,一轮银月滚金球. 远自湖北三千里,近到江南十六州: 美景一时观不透,天缘有分画中游. 前言 本章是重读<学习JavaScript数据结构 ...

  2. 重读《学习JavaScript数据结构与算法-第三版》-第2章 ECMAScript与TypeScript概述

    定场诗 八月中秋白露,路上行人凄凉: 小桥流水桂花香,日夜千思万想. 心中不得宁静,清早览罢文章, 十年寒苦在书房,方显才高志广. 前言 洛伊安妮·格罗纳女士所著的<学习JavaScript数据 ...

  3. 重读《学习JavaScript数据结构与算法-第三版》- 第6章 链表(一)

    定场诗 伤情最是晚凉天,憔悴厮人不堪言: 邀酒摧肠三杯醉.寻香惊梦五更寒. 钗头凤斜卿有泪,荼蘼花了我无缘: 小楼寂寞新雨月.也难如钩也难圆. 前言 本章为重读<学习JavaScript数据结构 ...

  4. 重读《学习JavaScript数据结构与算法-第三版》- 第3章 数组(一)

    定场诗 大将生来胆气豪,腰横秋水雁翎刀. 风吹鼍鼓山河动,电闪旌旗日月高. 天上麒麟原有种,穴中蝼蚁岂能逃. 太平待诏归来日,朕与先生解战袍. 此处应该有掌声... 前言 读<学习JavaScr ...

  5. 学习JavaScript数据结构与算法 (二)

    学习JavaScript数据结构与算法 的笔记 包含第四章队列, 第五章链表 本人所有文章首发在博客园: http://www.cnblogs.com/zhangrunhao/ 04队列 实现基本队列 ...

  6. 学习JavaScript数据结构与算法 (一)

    学习JavaScript数据结构与算法 的笔记, 包含一二三章 01基础 循环 斐波那契数列 var fibonaci = [1,1] for (var i = 2; i< 20;i++) { ...

  7. 学习JavaScript数据结构与算法---前端进阶系列

    学习建议 1.视频学习---认知 建议:在中国慕课上找"数据结构"相关的视频教程.中国大学MOOC 推荐清华大学.北京大学.浙江大学的教程,可先试看,然后根据自身的情况选择视频进行 ...

  8. 学习Javascript数据结构与算法(第2版)笔记(1)

    第 1 章 JavaScript简介 使用 Node.js 搭建 Web 服务器 npm install http-server -g http-server JavaScript 的类型有数字.字符 ...

  9. 学习JavaScript数据结构与算法 2/15

    第一章 JavaScript简介 js不同于C/C++,C#,JAVA,不是强类型语言. 通常,代码质量可以用全局变量和函数的数量来考量(数量越多越糟).因此,尽可能避免使用全局变量. JS数据类型 ...

随机推荐

  1. Connecting to the Network

    This lesson shows you how to implement a simple application that connects to the network. It explain ...

  2. 第二章 Session会话管理

    采用网址重写的缺点: 在有些Web浏览器中,URL限制为2000个字符. 仅当有链接要插入值时,值才能转换成后面的资源.此外,要把值添加到静态页面的链接中,可不是一件容易的事情. 网址重写必须在服务器 ...

  3. R018---RPA是什么东东?

    1.缘起 这个问题,很多文章回答过,一直想站在客户角度写个答案,今天正好. 2.RPA的名字  RPA是英文Robotic Process Automation的缩写,中文爱翻译为“流程自动化机器人” ...

  4. [USACO07FEB]银牛派对Silver Cow Party

    题目简叙: 寒假到了,N头牛都要去参加一场在编号为X(1≤X≤N)的牛的农场举行的派对(1≤N≤1000),农场之间有M(1≤M≤100000)条有向路,每条路长Ti(1≤Ti≤100). 每头牛参加 ...

  5. TensorFlow笔记-可视化Tensorboard

    可视化Tensorboard •数据序列化-events文件 TensorBoard 通过读取 TensorFlow 的事件文件来运行 •tf.summary.FileWriter('/tmp/ten ...

  6. http面试笔试常考知识点(一)

    1.什么是http HTTP是客户端和服务器端请求和应答的标准.通过使用Web浏览器.网络爬虫或者其它的工具,客户端发起一个到服务器上指定端口(默认端口为80)的HTTP请求.(我们称这个客户端)叫用 ...

  7. Android的日期选择器

    TimePicker(时间选择器) 方法 描述 Integer getCurrentHour () 返回当前设置的小时 Integer getCurrentMinute() 返回当前设置的分钟 boo ...

  8. Code blocks返回错误代码:Process returned -1073741819 (0xC0000005)

    循环语句访问链表时,返回了错误代码: 逐项排查后,发现是由while循环引起的: 附上出错代码: do{ L=L->post; printf("%05d %d %05d\n" ...

  9. windows server 2008 R2中建立ftp站点

    在windows server 2008 R2中建立ftp站点,要遵循以下步骤: (1) 开启IIS中的ftp服务: (2) 在IIS中建立ftp站点. 具体过程如下: (1) 开启IIS中的ftp服 ...

  10. 给最近正在找工作(iOS)的朋友一些建议/经验

    众所周知, iOS开发找工作越来越难, 企业要求越来越高,一方面是资本寒冬期+七八月是企业招人淡季, 另外一方面也是iOS市场饱和.最近有出去看新机会, 所以下面记录一下面试XimalayaFM的大概 ...