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 相关文章推荐
为jQuery增加join方法的实现代码
Nov 28 Javascript
js 单击式的下拉菜单效果实例
Aug 13 Javascript
jquery实现增加删除行的方法
Feb 03 Javascript
javascript下拉框选项单击事件的例子分享
Mar 04 Javascript
vue实现可增删查改的成绩单
Oct 27 Javascript
JavaScript对象封装的简单实现方法(3种方法)
Jan 03 Javascript
mui 打开新窗口的方式总结及注意事项
Aug 20 Javascript
React-Native之定时器Timer的实现代码
Oct 04 Javascript
WebGL学习教程之Three.js学习笔记(第一篇)
Apr 25 Javascript
vue-cli 3 全局过滤器的实例代码详解
Jun 03 Javascript
jquery+ajax实现上传图片并显示上传进度功能【附php后台接收】
Jun 06 jQuery
手把手教您实现react异步加载高阶组件
Apr 07 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中return 和 exit 、break和contiue 区别与用法
2012/04/09 PHP
浏览器关闭后,能继续执行的php函数(ignore_user_abort)
2012/08/01 PHP
PHP异常类及异常处理操作实例详解
2018/12/19 PHP
Yii框架的redis命令使用方法简单示例
2019/10/15 PHP
通过修改referer下载文件的方法
2008/05/11 Javascript
javaScript Array(数组)相关方法简述
2009/07/25 Javascript
页面中js执行顺序
2009/11/09 Javascript
js中各浏览器中鼠标按键值的差异
2011/04/07 Javascript
JS代码同步文本框内容的实例方法
2013/07/12 Javascript
jquery根据属性和index来查找属性值并操作
2014/07/25 Javascript
Javascript中使用A标签获取当前目录的绝对路径方法
2015/03/02 Javascript
js控制网页前进和后退的方法
2015/06/08 Javascript
chrome调试javascript详解
2015/10/21 Javascript
javascript实现加载xml文件的方法
2015/11/24 Javascript
JavaScript数组的定义及数字操作技巧
2016/06/06 Javascript
基于javascript实现按圆形排列DIV元素(二)
2016/12/02 Javascript
解决layui的form里的元素进行动态生成,验证失效的问题
2019/09/14 Javascript
javascript事件循环event loop的简单模型解释与应用分析
2020/03/14 Javascript
JavaScript实现tab栏切换效果
2020/03/16 Javascript
[48:44]2014 DOTA2国际邀请赛中国区预选赛5.21 TongFu VS HGT
2014/05/22 DOTA
Python的净值数据接口调用示例分享
2016/03/15 Python
itchat和matplotlib的结合使用爬取微信信息的实例
2017/08/25 Python
python3 实现的对象与json相互转换操作示例
2019/08/17 Python
python Web flask 视图内容和模板实现代码
2019/08/23 Python
python3.7 openpyxl 删除指定一列或者一行的代码
2019/10/08 Python
Python数据正态性检验实现过程
2020/04/18 Python
John Varvatos官方网站:设计师男士时装
2017/02/08 全球购物
军用级手机壳,专为冒险而建:Zizo Wireless
2019/08/07 全球购物
工程造价专业大专生求职信
2013/10/06 职场文书
幼儿园开学寄语
2014/04/03 职场文书
卖房协议书
2014/04/11 职场文书
教师爱岗敬业演讲稿
2014/05/05 职场文书
企业形象策划方案
2014/05/29 职场文书
卫校毕业生自我鉴定
2014/09/28 职场文书
部队2014年终工作总结
2014/11/27 职场文书
2015年度考核个人工作总结
2015/10/24 职场文书