JavaScript数据结构与算法之队列原理与用法实例详解


Posted in Javascript onNovember 22, 2017

本文实例讲述了JavaScript数据结构与算法之队列原理与用法。分享给大家供大家参考,具体如下:

队列是一种列表,不同的是队列只能在队尾插入元素,在队首删除元素。队列用于存储按顺序排列的数据,先进先出,这点和栈不一样(后入先出)。在栈中,最后入栈的元素反而被优先处理。我们现在可以把队列想象对我们去餐馆吃饭的情景,很多人排队吃饭,排在最前面的人先打饭。新来的人只能在后面排队。直到轮到他们为止。

一:对队列的操作

队列有2种主要的操作,向队尾中插入新元素enqueue()方法和删除队列中的队首的元素的dequeue()方法,另外我们还有一个读取队头的元素,这个方法我们可以叫front()方法。该方法返回队头元素等等方法。

看到如上描述,我们很多人可能会想到数组,数组里面也有2个方法和上面的方法功能类似,数组中push()方法也是往数组后面加入新元素,数组中shift()方法则可以删除数组里面的第一个元素。如下代码:

var arrs = [];
arrs.push("a");
arrs.push("b");
console.log(arrs); // ["a","b"];
arrs.shift();
console.log(arrs); // ['b'];

下面我们可以使用上面的数组中的push()shift()的2个方法来封装我们的队列Queue类;

1.  我们可以先定义一个构造函数Queue类,如下:

function Queue() {
  this.dataStore = [];
}

如上:this.dataStore = []; 空数组时存储队列中所有的元素的。

2. 向队尾中添加一个元素方法如下:

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

3. 删除队首的元素如下:

function dequeue() {
  return this.dataStore.shift()
}

4. 读取队首的元素如下:

function front() {
  return this.dataStore[0];
}

5. 读取队尾的元素如下:

function back() {
  return this.dataStore[this.dataStore.length - 1];
}

6. 显示队列中的所有元素

function toString() {
  var retStr = "";
  for(var i = 0; i < this.dataStore.length; ++i) {
    retStr += this.dataStore[i] + "\n";
  }
  return retStr;
}

7. 判断队列是否为空如下:

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

下面是完整的JS代码如下:

function Queue() {
  this.dataStore = [];
}
Queue.prototype = {
  // 向队尾添加一个元素
  enqueue: function(element) {
    this.dataStore.push(element);
  },
  // 删除队首的元素
  dequeue: function(){
    return this.dataStore.shift();
  },
  // 读取队首的元素
  front: function(){
    return this.dataStore[0];
  },
  // 读取队尾的元素
  back: function(){
    return this.dataStore[this.dataStore.length - 1];
  },
  // 显示队列内的所有元素
  toString: function(){
    var retStr = "";
    for(var i = 0; i < this.dataStore.length; ++i) {
      retStr += this.dataStore[i] + "\n";
    }
    return retStr;
  },
  // 判断队列是否为空
  empty: function(){
    if(this.dataStore.length == 0) {
      return true;
    }else {
      return false;
    }
  }
};

我们现在可以对以上代码测试下:如下:

var q = new Queue();
q.enqueue("a");
q.enqueue("b");
q.enqueue("c");
console.log(q.toString()); // a b c
q.dequeue();
console.log(q.toString()); // b c
console.log("Front of queue:" +q.front()); // b
console.log("Back of queue:" +q.back()); // c

二:使用队列对数据进行排序

比如对于 0 ~ 99 的数字进行排序,原理是:先对个位上的数字进行排序一次,然后对十位上的数字再进行排序一次。每个数字根据对应位上的数值被分在不同的盒子里面,然后对于个位上的数字采用除余数的方法,对于10位上的数字采用除法的方法,那么这种排序叫做 “基数排序”. 但是它不是最快的排序方法,但是它描述了一些有趣的队列使用方法。

比如如下数组:

var nums = ["50","12","95","7","90","3","74","81","91","72"];

1. 经过基数排序--个位排序后,数字被分配在不同的盒子里面。(在JS里面,我们可以分配在不同的队列Queue实例类里面)。如下

queues[0] = 50 或者 90
queues[1] = 81 或者 91
queues[2] = 12 或者 72
queues[3] = 3
queues[4] = 74
queues[5] = 95
queues[6] 
queues[7] = 7
queues[8]
queues[9]

根据盒子的顺序,对数字第一次个位排序后结果如下:

nums = [50,90,81,91,12,72,3,74,95,7]

2. 然后根据十位上的数值再将上次排序后的结果分配到不同的盒子中。如下:

queues[5] = 50
queues[9] = 90
queues[8] = 81
queues[9] = 91
queues[1] = 12
queues[7] = 72
queues[0] = 3
queues[7] = 74
queues[9] = 95
queues[0] = 7

最后,将盒子中的数字取出,组成一个新的列表,该列表即为排序好的数字。如下:

即可生成如下:

nums = [3,7,12,50,72,74,81,90,91,95];

如上使用队列列表盒子,可以实现这个算法,我们需要10个队列,每个队列对应一个数字,将所有队列保存在一个数组中,使用取余和除法操作决定个位和十位。算法的剩余部分将数字加入相应的队列,根据个位数值进行重新排序,然后再根据十位上的数值进行排序,结果加入排序好的数字。

下面根据个位或十位上的数值,将数字分配到相应队列的函数。

/*
* 根据个位或十位上的数值,将数字分配到相应队列的函数
* @param digit
* digit=1 表示先按个位来分配
* digit = 10 表示是按十位来分配的
* @param n 表示循环比较多少次 一般数组几个数字就比较多少次
*/
distribute: function(nums,queues,n,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]);
     }
   }
}

下面是从队列中收集数字的函数如下:

// 收集数字的函数
collect: function(queues,nums,n) {
  var i = 0;
  for(var digit = 0; digit < n; ++digit) {
    while(!queues[digit].empty()) {
      nums[i++] = queues[digit].dequeue();
    }
  }
}

由于上面省略了很多步骤,可能描述的不是很清楚,我们现在先来看看流程图,结合流程图,最后结合JS的所有代码就可以理解"基数排序的"基本原理了;下面我们可以看看如下的流程图;

JavaScript数据结构与算法之队列原理与用法实例详解

最后是所有的JS代码如下:

function Queue() {
  this.dataStore = [];
}
Queue.prototype = {
  // 向队尾添加一个元素
  enqueue: function(element) {
    this.dataStore.push(element);
  },
  // 删除队首的元素
  dequeue: function(){
    return this.dataStore.shift();
  },
  // 读取队首的元素
  front: function(){
    return this.dataStore[0];
  },
  // 读取队尾的元素
  back: function(){
    return this.dataStore[this.dataStore.length - 1];
  },
  // 显示队列内的所有元素
  toString: function(){
    var retStr = "";
    for(var i = 0; i < this.dataStore.length; ++i) {
      retStr += this.dataStore[i] + "\n";
    }
    return retStr;
  },
  // 判断队列是否为空
  empty: function(){
    if(this.dataStore.length == 0) {
      return true;
    }else {
      return false;
    }
  },
  /*
   * 根据个位或十位上的数值,将数字分配到相应队列的函数
   * @param digit
   * digit=1 表示先按个位来分配
   * digit = 10 表示是按十位来分配的
   * @param n 表示循环比较多少次 一般数组几个数字就比较多少次
   */
  distribute: function(nums,queues,n,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]);
      }
    }
  },
  // 收集数字的函数
  collect: function(queues,nums,n) {
    var i = 0;
    for(var digit = 0; digit < n; ++digit) {
      while(!queues[digit].empty()) {
        nums[i++] = queues[digit].dequeue();
      }
    }
  },
  dispArray: function(arr) {
    for(var i = 0; i < arr.length; ++i) {
      console.log(arr[i]);
    }
  }
};

下面的是对 "基数排序的" JS代码进行测试;如下代码:

var q = new Queue();
  q.enqueue("a");
  q.enqueue("b");
  q.enqueue("c");
console.log(q.toString());
q.dequeue();
console.log(q.toString());
console.log("Front of queue:" +q.front());
console.log("Back of queue:" +q.back());
var queues = [];
for(var i = 0; i < 10; ++i) {
   queues[i] = new Queue();
}
var nums = ["50","12","95","7","90","3","74","81","91","72"];
console.log("before radix sort: ");
console.log(nums);
q.distribute(nums,queues,10,1);
q.collect(queues,nums,10);
q.dispArray(nums);
console.log("分割线");
q.distribute(nums,queues,10,10);
q.collect(queues,nums,10);
q.dispArray(nums);

如上测试代码 大家可以运行下 就可以看到排序后的效果!

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

Javascript 相关文章推荐
Easy.Ajax 部分源代码 支持文件上传功能, 兼容所有主流浏览器
Feb 24 Javascript
JavaScript 上万关键字瞬间匹配实现代码
Jul 07 Javascript
node.js中的fs.createReadStream方法使用说明
Dec 17 Javascript
javascript面向对象快速入门实例
Jan 13 Javascript
Bootstrap每天必学之简单入门
Nov 19 Javascript
基于原生js淡入淡出函数封装(兼容IE)
Oct 20 Javascript
Angular-Touch库用法示例
Dec 22 Javascript
vue2.0+vuex+localStorage代办事项应用实现详解
May 31 Javascript
vue的过滤器filter实例详解
Sep 17 Javascript
vue登录页面cookie的使用及页面跳转代码
Jul 10 Javascript
使用JavaScript计算前一天和后一天的思路详解
Dec 20 Javascript
js判断鼠标移入移出方向的方法
Jun 24 Javascript
深入理解Vue官方文档梳理之全局API
Nov 22 #Javascript
初识 Vue.js 中的 *.Vue文件
Nov 22 #Javascript
chorme 浏览器记住密码后input黄色背景处理方法(两种)
Nov 22 #Javascript
基于JavaScript实现表格滚动分页
Nov 22 #Javascript
Vue.js表单标签中的单选按钮、复选按钮和下拉列表的取值问题
Nov 22 #Javascript
Vue官方文档梳理之全局配置
Nov 22 #Javascript
vue.js开发实现全局调用的MessageBox组件实例代码
Nov 22 #Javascript
You might like
一次编写,随处运行
2006/10/09 PHP
php下使用strpos需要注意 === 运算符
2010/07/17 PHP
谈谈你对Zend SAPIs(Zend SAPI Internals)的理解
2015/11/10 PHP
PHP实现伪静态方法汇总
2016/01/13 PHP
图片自动缩小的js代码,用以防止图片撑破页面
2007/03/12 Javascript
JavaScript 继承的实现
2009/07/09 Javascript
一个很简单的jquery+xml+ajax的无刷新树结构(无css,后台是c#)
2010/06/02 Javascript
js 绑定键盘鼠标事件示例代码
2014/02/12 Javascript
jQuery中outerWidth()方法用法实例
2015/01/19 Javascript
js实现进度条的方法
2015/02/13 Javascript
AngularJS基础学习笔记之表达式
2015/05/10 Javascript
javascript实现点击提交按钮后显示loading的方法
2015/07/03 Javascript
JavaScript判断页面加载完之后再执行预定函数的技巧
2016/05/17 Javascript
jQuery progressbar通过Ajax请求实现后台进度实时功能
2016/10/11 Javascript
javascript判断元素存在和判断元素存在于实时的dom中的方法
2017/01/17 Javascript
微信小程序 Toast自定义实例详解
2017/01/20 Javascript
利用JS实现简单的日期选择插件
2017/01/23 Javascript
vue+vuex+axios+echarts画一个动态更新的中国地图的方法
2017/12/19 Javascript
浅谈React前后端同构防止重复渲染
2018/01/05 Javascript
详解webpack 最简打包结果分析
2019/02/20 Javascript
JavaScript变速动画函数封装添加任意多个属性
2019/04/03 Javascript
修改Vue打包后的默认文件名操作
2020/08/12 Javascript
python在linux中输出带颜色的文字的方法
2014/06/19 Python
总结python实现父类调用两种方法的不同
2017/01/15 Python
离线安装Pyecharts的步骤以及依赖包流程
2020/04/23 Python
python如何实现int函数的方法示例
2018/02/19 Python
Python cookbook(数据结构与算法)找出序列中出现次数最多的元素算法示例
2018/03/15 Python
快速解决pandas.read_csv()乱码的问题
2018/06/15 Python
Python+OpenCV 实现图片无损旋转90°且无黑边
2019/12/12 Python
网页中的电话号码如何实现一键直呼效果_附示例
2016/03/15 HTML / CSS
美国摄影爱好者购物网站:Focus Camera
2016/10/21 全球购物
adidas瑞典官方网站:购买阿迪达斯鞋子和运动服
2019/12/11 全球购物
金融专业推荐信
2013/11/14 职场文书
新学期家长寄语
2014/01/19 职场文书
初中英语演讲稿
2014/04/29 职场文书
2015年银行客户经理工作总结
2015/04/01 职场文书