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 相关文章推荐
用js得到网页中所有的div的id
Oct 19 Javascript
用 Javascript 验证表单(form)中的单选(radio)值
Sep 08 Javascript
Mootools 1.2教程 Fx.Morph、Fx选项和Fx事件
Sep 15 Javascript
JavaScript delete 属性的使用
Oct 08 Javascript
利用JQuery+EasyDrag 实现弹出可拖动的Div,同时向Div传值,然后返回Div选中的值
Oct 24 Javascript
浅谈Javascript中匀速运动的停止条件
Dec 19 Javascript
Jqgrid之强大的表格插件应用
Dec 02 Javascript
详解javascript高级定时器
Dec 31 Javascript
JavaScript驾驭网页-DOM
Mar 24 Javascript
jQuery、zepto、js常用小技巧
Feb 12 Javascript
使用AngularJS2中的指令实现按钮的切换效果
Mar 27 Javascript
JavaScript实现简单进度条效果
Mar 25 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+oracle 分页类
2006/10/09 PHP
php创建sprite
2014/02/11 PHP
PHP中PDO连接数据库中各种DNS设置方法小结
2016/05/13 PHP
PHP编写简单的App接口
2016/08/28 PHP
jQuery的.live()和.die() 使用介绍
2011/09/10 Javascript
Js中setTimeout()和setInterval() 何时被调用执行的用法
2013/04/12 Javascript
jQuery实现滚动鼠标放大缩小图片的方法(附demo源码下载)
2016/03/05 Javascript
JavaScript基于Dom操作实现查找、修改HTML元素的内容及属性的方法
2017/01/20 Javascript
js中setTimeout的妙用--防止循环超时
2017/03/06 Javascript
文本溢出插件jquery.dotdotdot.js使用方法详解
2017/06/22 jQuery
JavaScript贪吃蛇小组件实例代码
2017/08/20 Javascript
实现div滚动条默认最底部以及默认最右边的示例代码
2017/11/15 Javascript
[02:06]2018完美世界全国高校联赛秋季赛开始报名(附彩蛋)
2018/09/03 DOTA
Python异常学习笔记
2015/02/03 Python
对于Python中线程问题的简单讲解
2015/04/03 Python
python单元测试unittest实例详解
2015/05/11 Python
Python过滤列表用法实例分析
2016/04/29 Python
PyCharm 常用快捷键和设置方法
2017/12/20 Python
Python实现的登录验证系统完整案例【基于搭建的MVC框架】
2019/04/12 Python
详解python uiautomator2 watcher的使用方法
2019/09/09 Python
Python基于Tensor FLow的图像处理操作详解
2020/01/15 Python
Tensorflow累加的实现案例
2020/02/05 Python
关于Python字符编码与二进制不得不说的一些事
2020/10/04 Python
pycharm 2020.2.4 pip install Flask 报错 Error:Non-zero exit code的问题
2020/12/04 Python
纯CSS3制作漂亮带动画效果的主机价格表
2015/04/25 HTML / CSS
HTML5中Localstorage的使用教程
2015/07/09 HTML / CSS
《孔子游春》教学反思
2014/02/25 职场文书
中等生评语大全
2014/05/04 职场文书
药剂专业自荐书
2014/06/20 职场文书
医院领导班子整改方案
2014/10/01 职场文书
关于拾金不昧的感谢信
2015/01/21 职场文书
植树节新闻稿
2015/07/17 职场文书
KTV员工管理制度
2015/08/06 职场文书
大学社团活动总结怎么写
2019/06/21 职场文书
这样写python注释让代码更加的优雅
2021/06/02 Python
Python循环之while无限迭代
2022/04/30 Python