用js来实现那些数据结构06(队列)

  其实队列跟栈有很多相似的地方,包括其中的一些方法和使用方式,只是队列使用了与栈完全不同的原则,栈是后进先出原则,而队列是先进先出(First In First Out)。

一、队列

队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。队列中没有元素时,称为空队列。
队列的数据元素又称为队列元素。在队列中插入一个队列元素称为入队,从队列中删除一个队列元素称为出队。因为队列只允许在一端插入,在另一端删除,所以只有最早进入队列的元素才能最先从队列中删除,故队列又称为先进先出(FIFO—first in first out)线性表。
我们对队列有了基本的了解,那么我们来看看如何实现队列。其实跟栈的实现极为类似,只是入队和出队的方法稍有不同,那么我们来看看一个完整的队列需要哪些方法:
1、enqueue(element(s)),入队,向队列尾部添加一个或者多个元素。
2、dequeue(),出队,移除队列中的第一个元素,也就是队列最前面的元素,并返回该元素。
3、front(),获取队列最前面的元素,返回队列中第一个元素(最先被添加,也是最先被移除的元素)。队列并不移除该元素。
4、isEmpty(),判断队列是否不包含任何元素。
5、size(),返回队列的元素总数。
 //声明Queue类function Queue() {//声明并初始化一个用来存放队列元素的数组。let items = [];//添加队列元素this.enqueue = function (element) {items.push(element)};//移除并返回该队列元素this.dequeue = function () {return items.shift(); }; //获取队列头部元素 this.front = function () { return items[0]; }; //判断队列元素是否为空 this.isEmpty = function () { return items.length == 0; }; //获取队列元素个数 this.size = function () { return items.length; }; //打印该队列 this.print = function () { console.log(items.toString()) }; } const queue = new Queue(); console.log(queue.isEmpty()); // outputs true queue.enqueue('John'); queue.enqueue('Jack'); queue.print(); // John,Jack queue.enqueue('Camila'); queue.print(); // John,Jack,Camila console.log(queue.size()); // outputs 3 console.log(queue.isEmpty()); // outputs false queue.dequeue(); // remove John queue.dequeue(); // remove Jack queue.print(); // Camila

  上面我们就已经实现了队列这种数据结构,同样的,我们是否可以稍微改造一下,让队列的实现看起来更加优美一点。

let Queue = (function () {const items = new WeakMap();class Queue {constructor () {
        //强调一下,这里items是WeakMap类型的数据,而WeakMap是键值对,有专属的set和get方法来获取和设置值,
        //所以这里给this设置了[],即以this为键名,[]为值,所以该方法形成的队列仍旧是对数组的操作items.set(this,[]);}enqueue(element) {let q = items.get(this);//这里的q就相当于是[]q.push(element);}dequeue() {let q = items.get(this); let r = q.shift(); return r; } front() { return items.get(this)[0]; } isEmpty() { return items.get(this).length == 0; } size() { return items.get(this).length; } print() { console.log(items.get(this)); } } return Queue; })()

  其实到这里队列就基本介绍完了,但是感觉实在有点糊弄人啊。所以就把剩下的内容都在这一篇文章写完吧。

二、优先队列
我们说完了队列,那么我们看看什么是优先队列。普通的队列是一种先进先出的数据结构,元素在队列尾追加,而从队列头删除。在优先队列中,元素被赋予优先级。当访问元素时,具有最高优先级的元素最先删除。优先队列具有最高级先出 (first in, largest out)的行为特征。就像是我们在窗口买票,机场排队,正常来说我们都是依照排队的顺序从队列的最前面开始依次进入,但是有规定老人孩子军人等优先,那么就赋予了该老人(孩子军人)插队的权利。而优先队列,同样就是给特定元素赋予插队(优先级)的权利。我想要入队,并不一定是直接到尾部。而是根据我设定的优先级来插入队列。
其实优先队列在实现上不同的地方是队列元素的设定和入队方法的不同(这里其实有两种实现方式,一个是按照优先级入列,一个是按照优先级出列,这里我们只用第一种方式实现)。下面我们就看看如何实现优先队列吧。
  //声明Queue类function PriorityQueue() {//声明并初始化一个用来存放队列元素的数组。let items = [];//创建一个拥有优先级的元素类function QueueElement(element,priority) {this.element = element;this.priority = priority; } //添加队列元素 this.enqueue = function (element,priority) { let queueElement = new QueueElement(element,priority); let added = false; //遍历队列元素,1的优先级最高,一次类推,如果当前元素优先级大于items[i],那么就把该元素放在items[i]前面。 //splice方法的第二的参数如果为0,那么则把第三个参数添加到i前面。 for(let i = 0; i < items.length; i ) { if(queueElement.priority < items[i].priority) { items.splice(i,0,queueElement); added = true;break; } } // 通过added判断是否可以直接把元素入列。 if(!added) { items.push(queueElement); } }; //移除并返回该队列元素 this.dequeue = function () { return items.shift(); }; //获取队列头部元素 this.front = function () { return items[0]; }; //判断队列元素是否为空 this.isEmpty = function () { return items.length == 0; }; //获取队列元素个数 this.size = function () { return items.length; }; //循环打印元素及其优先级“``”是ES6的模板字符串 this.print = function () { for(let i = 0; i < items.length; i ) { console.log(`${items[i].element} - ${items[i].priority}`); } }; } const queue = new PriorityQueue(); console.log(queue.isEmpty()); // outputs true  queue.enqueue('zaking',2); queue.enqueue('linbo',6); queue.enqueue('queue',5); queue.enqueue('ada',3); queue.enqueue('John',1); queue.enqueue('Jack',2); queue.enqueue('Camila',3); queue.enqueue('zak',3); queue.print(); 

  主要的更改在于队列元素的设置和enqueue方法,由于需要为每一个循环队列的元素设置优先级,所以这里稍微更改了一下队列的元素,使其带有两个参数(元素自身和优先级),那么既然要根据不同的优先级来插入队列,所以循环队列的enqueue方法也就需要循环整个队列去判断要插入到哪里。

其实这个优先队列的实现并不是很好,比如我不传第二优先级参数,那么队列打印的时候该参数就是undefined,而且在不传参数的时候应该默认为最末优先级。大家可以试着去修改一下代码,使其看起来更符合实际。
三、循环队列
  除了优先队列以外还有循环队列,循环队列的一个比较容易想象的例子就是击鼓传花游戏,游戏规则就不说了大家小时候都玩过,我们看看如何实现击鼓传花游戏。
function hotPotato(nameList, num) {const queue = new Queue();//把所有的名单(nameList)依次入列for (let i = 0; i < nameList.length; i  ) {queue.enqueue(nameList[i]);}//声明当前被淘汰的人员名称let eliminated = '';//如果队列中的元素大于一个,说明还没有最后的赢家,如果只剩下一个,就出列该最后赢家while (queue.size() > 1) { //循环当前队列num次,把队列头部的“出列元素”再入列。 for (let i = 0; i < num; i ) { queue.enqueue(queue.dequeue()); } //循环结束后,出列当前队列的元素,也就是淘汰者。 eliminated = queue.dequeue(); queue.print(); console.log(eliminated "被淘汰"); } return queue.dequeue(); } let names = ["zak","zaking","james","lili","bole","londo","fali"] console.log(hotPotato(names,7))

  上面的方法,每次循环都会依次把头部元素放入到尾部,就实现了一个圈,然后我们以循环结束后,队列最前端的元素视为淘汰,直到最后只剩下一个元素,也就真实的模拟了击鼓传花游戏。

 

  最后,由于本人水平有限,能力与大神仍相差甚远,若有错误或不明之处,还望大家不吝赐教指正。非常感谢!


更多专业前端知识,请上 【猿2048】www.mk2048.com

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/361877.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

探索SwitchYard 2.0.0.Alpha2快速入门

在我的最后一篇文章中&#xff0c;我解释了如何在WildFly 8.1上使用SwitchYard。 同时&#xff0c;该项目很忙&#xff0c;并发布了另一个Alpha2。 这是一个很好的机会&#xff0c;在这里浏览快速入门并刷新您的记忆。 除了版本更改之外&#xff0c;您仍然可以使用较早的博客来…

MySQL之触发器

二&#xff1a;触发器 1. 什么是触发器 触发器&#xff0c;是一段与某个表相关的sql语句&#xff0c;会在某个时间点&#xff0c;满足某个条件后自动触发执行 其中两个关键因素&#xff1a; 时间点 * 事件发生前&#xff0c;before|事件发生后 after事件 * update delete inser…

PowerDesigner使用技巧

PowerDesigner使用MySQL的auto_increment   ◇问题描述&#xff1a;   PD怎样能使主键id使用MySQL的auto_increment呢&#xff1f; ◇解决方法&#xff1a;    打开table properties窗口 → columns → 选中id列 → 打开columns properties窗口 → 勾选identity即可   …

走进webpack(1)--环境拆分及模块化

初级的文章和demo已经基本完成了&#xff0c;代码也已经上传到了我的github上&#xff0c;如果你对webpack的使用并不是十分了解&#xff0c;那么建议你回头看下走近系列&#xff0c;里面包括了当前项目中使用频繁的插件&#xff0c;loader的讲解。以及基本的webpack配置&#…

适用于微服务架构的Apache Camel

在知道微服务架构被称为之前&#xff0c;我一直在使用它们。 我曾经使用过由隔离模块组成的管道应用程序&#xff0c;这些模块通过队列相互交互。 从那时起&#xff0c;许多&#xff08;前&#xff09;ThoughtWorks专家讨论了微服务。 首先是 Fred George&#xff0c; 然后是 J…

题解 P3811 【【模板】乘法逆元】

P3811 【模板】乘法逆元 一个刚学数论的萌新&#xff0c;总结了一下这题的大部分做法 //一、费马小定理快速幂 O(nlogn) 64分 #include<cstdio> using namespace std; typedef long long ll; int a,b; inline ll pow(ll x,ll p) {ll ans1;x%b;while(p) {if (p&1) an…

QueryString加密

有些人不想由URL暴露一些訊息&#xff0c;除了可以使用URL Rewrite之外&#xff0c;其實簡便一點的方法還有使用編碼or加密來達到偽裝的目的。使用Base64的原因是因為他的編碼不會有難以接受的特殊字元(註1)&#xff0c;你也可以用其他的編碼or加密算法替代(註2)。其實這邊已經…

即时大数据流处理=即时风暴

在Ubuntu背后的公司Canonical&#xff0c;每6个月进行一次技术工作&#xff0c;以第一手测试我们的工具并向其他人展示新想法。 这次&#xff0c;我创建了一个即时大数据解决方案&#xff0c;更具体地讲是“即时风暴”。 Storm现在是Apache基金会的一部分&#xff0c;但以前St…

webstorm中vue项目--运行配制

## npm搭建的项目&#xff0c;需要运行npm run dev来启动 webstorm作为一款优秀的编辑器&#xff0c;通过配置运行设置&#xff0c;达到一键运行 1.添加node.js配置 2.configuration->node interpreter : 路径/node.exe 3.configuration->working directory&#xff1a; …

VS2010 自动化整理代码(1)--- VS正则表达替换 PK Vim

自从开始在VS2010的IDE中开始用正则表达式修改 最近为了给Fortran找个好一点的编辑器&#xff0c;又开始使用Vim了。Vim是久负盛名的编辑器之神&#xff0c;可我们习惯了Visual Studio的智能提示等方便的操作&#xff0c;就总在琢磨要是VS 1. VS正则表达替换 PK Vim 这是善用…

Java基础(多态的理解与应用)

1.多态概述 多态是继封装、继承之后&#xff0c;面向对象的第三大特性。 多态现实意义理解&#xff1a; 现实事物经常会体现出多种形态&#xff0c;如学生&#xff0c;学生是人的一种&#xff0c;则一个具体的同学张三既是学生也是人&#xff0c;即出现两种形态。 …

Java并发教程–锁定:内在锁

在以前的文章中&#xff0c;我们回顾了在不同线程之间共享数据的一些主要风险&#xff08;例如原子性和可见性 &#xff09;以及如何设计类以安全地共享&#xff08; 线程安全的设计 &#xff09;。 但是&#xff0c;在许多情况下&#xff0c;我们将需要共享可变数据&#xff0…

小程序在wxml页面中取整

小程序无法像html中&#xff0c;在页面中直接parseInt() index.wxml {{price | Int}} 小程序还有另一种处理方法 wxs 是一种类似于js脚本的东西 filters.wxs var filters {toFix: function (value) {return parseFloat(value)} } module.exports {toFix: filters.toFix } …

2019.7.16考试总结

对于这个狗屎成绩我不想说什么&#xff0c;&#xff0c;&#xff0c;&#xff0c;&#xff0c;前两次考炸也就算了&#xff0c;主要因为不会&#xff0c;这次考成这狗屎&#xff0c;是因为手残眼瘸大脑间歇性抽搐 T1&#xff1a;我是菜鸡&#xff0c;我是蒟蒻&#xff0c;我好菜…

PrimeFaces Extensions中的全新JSF组件

PrimeFaces扩展团队很高兴宣布即将推出的3.0.0主要版本的几个新组件。 我们的新提交人Francesco Strazzullo为该项目提供了“ Turbo Boost”&#xff0c;并带来了至少6个已成功集成的 JSF组件&#xff01; 当前的开发状态是OpenShift上的deployet – 请查看展示柜。以下是有关添…

Application Verifier

老徐 says Application Verifier can help to check the memory leak issue of the notepad app.转载于:https://www.cnblogs.com/backpacker/archive/2011/11/16/2250648.html

15 个最新的 CSS3 教程

1. 创建一个漂亮的图标 这个教程将教你如何用纯CSS3创建一个图中的图标2. CSS3 图片样式 这个教程将教你如何使用 box-shadow, border-radius和transition。3. CSS3 Transition 的模糊效果4. 实用的CSS3圆角表格5. 创建纯CSS3的票式标签6. 原始的鼠标浮动效果 这个教程将创建缩…

运行时类加载以支持不断变化的API

我维护一个IntelliJ插件 &#xff0c;可以改善编写Spock规范的体验。 这个项目的挑战是在单个代码库中支持多个不兼容的IntelliJ API版本。 回想起来&#xff0c;该解决方案很简单&#xff08;这是狂野的适配器模式的一个示例&#xff09;&#xff0c;但最初它需要一些思想和示…

急救: Autodesk MapGuide Studio - Preview在MapGuide Open Source环境不能进行中文标注

MapGuide环境: 从官方mapguide.osgeo.org下载的最新版Mapguide Open Source1.1 和 MapGuide Open Source Web Server Extension开发环境: vs2005 .net2问题详述&#xff1a;对于图层Layer1. 选中后实体可以查询中文属性信息。具体设置在Properties displayed in Viewer&#xf…

解决新版本webpack vue-cli生成文件没有dev.server.js问题

新版本webpack生成的dev.server.js 在webpack.dev.conf.js中webpack.dev.conf.jsconst axios require(axios) const express require(express) const app express() const apiRoutes express.Router() app.use(/api, apiRoutes)然后找到devserver 这里可以配置路由devServe…