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 相关文章推荐
用Javascript做flash做的事..才完成的一个类.Auntion Action var 0.1
Feb 23 Javascript
JavaScript学习笔记之获取当前目录的实现代码
Dec 14 Javascript
JQuery 返回布尔值Is()条件判断方法代码
May 14 Javascript
file控件选择上传文件确定后触发的js事件是哪个
Mar 17 Javascript
5个可以帮你理解JavaScript核心闭包和作用域的小例子
Oct 08 Javascript
js控制网页背景音乐播放与停止的方法
Feb 06 Javascript
详解用webpack把我们的业务模块分开打包的方法
Jul 20 Javascript
Vue.js进行查询操作的实例详解
Aug 25 Javascript
浅谈react前后端同构渲染
Sep 20 Javascript
node thread.sleep实现示例
Jun 20 Javascript
node-red File读取好保存实例讲解
Sep 11 Javascript
ES6新增的数组知识实例小结
May 23 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 MVC模式在网站架构中的实现分析
2010/03/04 PHP
PHP实现的折半查询算法示例
2017/10/09 PHP
Smarty模板变量与调节器实例详解
2019/07/20 PHP
Tab页界面,用jQuery及Ajax技术实现
2009/09/21 Javascript
jQuery 点击图片跳转上一张或下一张功能的实现代码
2010/03/12 Javascript
javascript跨域刷新实现代码
2011/01/01 Javascript
打印json对象的内容及JSON.stringify函数应用
2013/03/29 Javascript
JavaScript利用正则表达式去除日期中的“-”
2014/07/01 Javascript
js读写json文件实例代码
2014/10/21 Javascript
jQuery超酷平面式时钟效果代码分享
2020/03/30 Javascript
JavaScript中rem布局在react中的应用
2015/12/09 Javascript
浅谈JS中json数据的处理
2016/06/30 Javascript
jquery对Json的各种遍历方法总结(必看篇)
2016/09/29 Javascript
AngularJS操作键值对象类似java的hashmap(填坑小结)
2016/11/12 Javascript
原生js实现打字动画游戏
2017/02/04 Javascript
详解VUE-地区选择器(V-Distpicker)组件使用心得
2018/05/07 Javascript
bootstrap模态框关闭后清除模态框的数据方法
2018/08/10 Javascript
JavaScript对象拷贝与赋值操作实例分析
2018/12/10 Javascript
微信公众平台获取access_token的方法步骤
2019/03/29 Javascript
javascript实现计算器功能
2020/03/30 Javascript
JS判断数组是否包含某元素实现方法汇总
2020/06/24 Javascript
基于Electron实现桌面应用开发代码实例
2020/07/07 Javascript
解决vue addRoutes不生效问题
2020/08/04 Javascript
Python中的zip函数使用示例
2015/01/29 Python
浅谈Python实现贪心算法与活动安排问题
2017/12/19 Python
css3设置box-pack和box-align让div里面的元素垂直居中
2014/09/01 HTML / CSS
利用HTML5中Geolocation获取地理位置调用Google Map API在Google Map上定位
2013/01/23 HTML / CSS
财务助理岗位职责
2013/11/10 职场文书
奥巴马演讲稿
2014/01/08 职场文书
培训演讲稿范文
2014/01/12 职场文书
电子信息专业自荐书
2014/02/04 职场文书
中药专业自荐信范文
2014/03/18 职场文书
2015年十一国庆节演讲稿
2015/03/20 职场文书
大学班长竞选稿
2015/11/20 职场文书
关于k8s环境部署mysql主从的问题
2022/03/13 MySQL
mysql序号rownum行号实现方式
2022/12/24 MySQL