JS中的算法与数据结构之队列(Queue)实例详解


Posted in Javascript onAugust 20, 2019

本文实例讲述了JS中的算法与数据结构之队列(Queue)。分享给大家供大家参考,具体如下:

队列(Queue)

我们之前说到了栈,它是一种比较高效的数据结构,遵循 先入后出(LIFO,last-in-first-out) 的原则。而今天我们要讨论的队列,它也是一种特殊的列表,它与栈不同的是, 队列只能在队尾插入元素,在队首删除元素,就像我们平时排队买票一样~

队列用于存储按顺序排列的数据,遵循 先进先出(FIFO,First-In-First-Out) 的原则,也是计算机常用的一种数据结构,别用于很多地方,比如提交给操作系统的一系列进程,打印池任务等。

同栈有点类似,队列的操作主要也是有两种:向队列中插入新元素和删除队列中的元素,即入队和出队操作,我们采用 enqueue 和 dequeue 两个方法。

除此之外,队列还有一些其他的操作,比如读取队首的元素,该操作仅返回对头元素并不将它从队列中删除,类似栈的 peek 方法;back 方法读取队尾的元素;toString 方法可以打印当前队列中所有的元素;clear 方法清空当前队列等。

JS中的算法与数据结构之队列(Queue)实例详解 
队列数据定义

我们定义好数据类型,可以通过JS中的数组去实现它。

队列的实现

//定义队列

function Queue(){
 this.dataStore = [];
 this.enqueue = enqueue;  //入队
 this.dequeue = dequeue;  //出队
 this.front = front;   //查看队首元素
 this.back = back;   //查看队尾元素
 this.toString = toString; //显示队列所有元素
 this.clear = clear;   //清空当前队列
 this.empty = empty;   //判断当前队列是否为空
}

我们先来实现入队操作:

enqueue:向队列添加元素

//向队列末尾添加一个元素,直接调用 push 方法即可

function enqueue ( element ) {
 this.dataStore.push( element );
}

因为JS中的数组具有其他语言没有的有点,可以直接利用 shift 方法删除数组的第一个元素,因此,出队操作的实现就变得很简单了。

dequeue:删除队首的元素

//删除队列首的元素,可以利用 JS 数组中的 shift 方法

function dequeue () {
 if( this.empty() ) return 'This queue is empty';
 else this.dataStore.shift();
}

我们注意的,上面我做了一个判断,队列是否还有元素,因为去删除空队列的元素是没有意义的,那么,我们就来看看 empty 方法是如何实现的。

empty:判断队列是否为空

//我们通过判断 dataStore 的长度就可知道队列是否为空

function empty(){
 if( this.dataStore.length == 0 ) return true;
 else return false;
}

我们先来看看测试一下这几个方法,

var queue = new Queue();

console.log( queue.empty() );  //true

//添加几个元素
queue.enqueue('Apple');
queue.enqueue('Banana');
queue.enqueue('Pear');

console.log( queue.empty() );  // false

现在,我不知道谁在第一个,谁是最后一个,我们可以利用 front 和 back 方法分别来查看,

front:查看队首元素

//查看队首元素,直接返回数组首个元素即可

function front(){
 if( this.empty() ) return 'This queue is empty';
 else return this.dataStore[0];
}

back:查看队尾元素

//查看队首元素,直接返回数组最后一个元素即可

//读取队列尾的元素
function back () {
 if( this.empty() ) return 'This queue is empty';
 else return this.dataStore[ this.dataStore.length - 1 ];
}

我们先看看对不对:

//查看队首元素
console.log( queue.front() ); // Apple
//查看队尾元素 
console.log( queue.back() ); // Pear

//出队
queue.dequeue();

//查看队首元素
console.log( queue.front() ); // Banana
//查看队尾元素 
console.log( queue.back() ); // Pear

没问题!现在,我想看看,总共有多少水果,toString方法来实现,

toString:查看队列中所有元素

//查看对了所有元素,我这里采用数组的 join 方法实现

function toString(){
 return this.dataStore.join('\n');
}

现在,你可以看看你还有什么水果没吃的了,

console.log( queue.toString() )  // Apple
         // Banana
         // Pear

我们就剩下一个 clear 方法了,如果你已经把所有水果都吃完了,那么你应该使用 clear 方法,

//清空当前队列,也很简单,我们直接将 dataStore 数值清空即可

function clear(){
 delete this.dataStore;
 this.dataStor = [];
}

至此,我们已经用JS实现了一个队列,怎么样,是不是觉得JS的数组超级好用,省去了不少麻烦,有木有!!

//清空队列

queue.clear();

console.log( queue.empty() ); // true

下面,我们利用队列来实现基数排序。

基数排序(radix sort)属于“分配式排序”(distribution sort),它是透过键值的部份资讯,将要排序的元素分配至某些“桶”中,藉以达到排序的作用,基数排序法是属于稳定性的排序,其时间复杂度为O (nlog(r)m),其中r为所采取的基数,而m为堆数,在某些时候,基数排序法的效率高于其它的稳定性排序法。

先看一下基数排序的的实现步骤(以两位数为例),需要扫描两次,第一次按个位数字进行排序,第二次按十位数字排序,每个数字根据对应的数值分配到到不同的盒子里,最后将盒子的数字依次取出,组成新的列表即为排序好的数字。

  1. 假设我们有一串数字,分别为 73, 22, 93, 43, 55, 14, 28, 65, 39, 81
  2. 首先根据个位数字排序,放到不同的盒子里,如下图

    JS中的算法与数据结构之队列(Queue)实例详解
    第一次排序
  3. 接下来将这些盒子中的数值重新串接起来,成为以下的数列:81, 22, 73, 93, 43, 14, 55, 65, 28, 39
  4. 然后根据十位数字排序,再放到不同的盒子里,如下图

    JS中的算法与数据结构之队列(Queue)实例详解
    第二次排序
  5. 接下来将这些盒子中的数值重新串接起来,整个数列已经排序完毕:14, 22, 28, 39, 43, 55, 65, 73, 81, 93

我们已经了解了基数排序的算法思想,接着我们要结合队列去实现它,一起来看看吧。

//基数排序

var queues = []; //定义队列数组
var nums = [];  //定义数字数组

//选十个0~99的随机数进行排序
for ( var i = 0 ; i < 10 ; i ++ ){
 queues[i] = new Queue();
 nums[i] = Math.floor( Math.random() * 101 );
}

//排序之前
console.log( 'before radix sort: ' + nums );

//基数排序
distribution( nums , queues , 10 , 1 );
collect( queues , nums );
distribution( nums , queues , 10 , 10 );
collect( queues , nums );

//排序之后
console.info('after radix sort: ' + nums );

//根据相应的(个位和十位)数值,将数字分配到相应队列

function distribution ( nums , queues , n , digit ) { //digit表示个位或者十位的值
 for( var i = 0 ; i < n ; i++ ){
  if( digit == 1){
   queues[ nums[i] % 10 ].enqueue( nums[i] );
  }else{
   queues[ Math.floor( nums[i] / 10 ) ].enqueue( nums[i] );
  }
 }
}

//从队列中收集数字

function collect ( queues , nums ) {
 var i = 0;
 for ( var digit = 0 ; digit < 10 ; digit ++ ){
  while ( !queues[digit].empty() ){
   nums[ i++ ] = queues[digit].front();
   queues[digit].dequeue();
  }
 }
}

我这里贴出两组测试的结果,大家自己动手实践一下。

//第一组测试

before radix sort: 23,39,2,67,90,41,47,21,98,13
after radix sort: 2,13,21,23,39,41,47,67,90,98

//第二组测试

before radix sort: 29,62,38,16,55,26,33,54,76,65
after radix sort: 16,26,29,33,38,54,55,62,65,76

至此,我们队列也就告一段落了,大家还可以往深入拓展,比如优先队列,循环队列等,希望大家能发散思维,多动手实践,一起加油!

感兴趣的朋友可以使用在线HTML/CSS/JavaScript代码运行工具:http://tools.3water.com/code/HtmlJsRun测试上述代码运行效果。

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
摘自百度的图片轮换效果代码
Nov 19 Javascript
很多人都是用下面的js刷新站IP和PV
Sep 05 Javascript
JS array 数组详解
Mar 22 Javascript
点击标签切换和自动切换DIV选项卡
Aug 10 Javascript
html的DOM中Event对象onblur事件用法实例
Jan 21 Javascript
解决js页面滚动效果scrollTop在FireFox与Chrome浏览器间的兼容问题的方法
Dec 03 Javascript
Node.js 回调函数实例详解
Jul 06 Javascript
详解react-native-fs插件的使用以及遇到的坑
Sep 12 Javascript
Vue-router结合transition实现app前进后退动画切换效果的实例
Oct 11 Javascript
vue中使用cookies和crypto-js实现记住密码和加密的方法
Oct 18 Javascript
js获取本日、本周、本月的时间代码
Feb 01 Javascript
three.js如何实现3D动态文字效果
Mar 03 Javascript
JS中的算法与数据结构之栈(Stack)实例详解
Aug 20 #Javascript
小程序如何在不同设备上自适应生成海报的实现方法
Aug 20 #Javascript
使用 Vue 实现一个虚拟列表的方法
Aug 20 #Javascript
基于vue手写tree插件的那点事儿
Aug 20 #Javascript
详解基于原生JS验证表单组件xy-form
Aug 20 #Javascript
详解微信小程序图片地扯转base64解决方案
Aug 18 #Javascript
wx-charts 微信小程序图表插件的具体使用
Aug 18 #Javascript
You might like
php读取30天之内的根据算法排序的代码
2008/04/06 PHP
Discuz Uchome ajaxpost小技巧
2011/01/04 PHP
9条PHP编程小知识及易犯的小错误
2015/01/22 PHP
php选择排序法实现数组排序实例分析
2015/02/16 PHP
PHP使用递归生成文章树
2015/04/21 PHP
PHP递归获取目录内所有文件的实现方法
2016/11/01 PHP
CodeIgniter框架钩子机制实现方法【hooks类】
2018/08/21 PHP
Laravel核心解读之异常处理的实践过程
2019/02/24 PHP
云网广告中的代码,提示出错,大家找找
2006/11/21 Javascript
javascript当onmousedown、onmouseup、onclick同时应用于同一个标签节点Element
2010/01/05 Javascript
js 复制或插入Html的实现方法小结
2010/05/19 Javascript
JQuery入门——用bind方法绑定事件处理函数应用介绍
2013/02/05 Javascript
MultiSelect左右选择控件的设计与实现介绍
2013/06/08 Javascript
基于JavaScript实现移除(删除)数组中指定元素
2016/01/04 Javascript
JavaScript 函数的执行过程
2016/05/09 Javascript
javascript实现的图片预览功能
2017/03/25 Javascript
react以create-react-app为基础创建项目
2018/03/14 Javascript
Nodejs监听日志文件的变化的过程解析
2019/08/04 NodeJs
Vue调用后端java接口的实例代码
2019/10/28 Javascript
[02:08]DOTA2英雄基础教程 马格纳斯
2014/01/17 DOTA
Python的词法分析与语法分析
2013/05/18 Python
Python的另外几种语言实现
2015/01/29 Python
Linux RedHat下安装Python2.7开发环境
2017/05/20 Python
python3 unicode列表转换为中文的实例
2018/10/26 Python
python PrettyTable模块的安装与简单应用
2019/01/11 Python
浅谈Python 列表字典赋值的陷阱
2019/01/20 Python
python装饰器的特性原理详解
2019/12/25 Python
python实现串口通信的示例代码
2020/02/10 Python
pyinstaller打包单文件时--uac-admin选项不起作用怎么办
2020/04/15 Python
一道写SQL的面试题和答案
2013/11/19 面试题
2014年机关党建工作总结
2014/11/11 职场文书
2015年初中元旦晚会活动总结
2014/11/28 职场文书
领导干部学习三严三实心得体会
2016/01/05 职场文书
读《皮囊》有感:理解是对他人的最大的善举
2019/11/14 职场文书
如何用 Python 子进程关闭 Excel 自动化中的弹窗
2021/05/07 Python
MongoDB数据库之添删改查
2022/04/26 MongoDB