用js来实现那些数据结构(队列)

转载 2018年04月17日 15:06:33

其实队列跟栈有很多相似的地方,包括其中的一些方法和使用方式,只是队列使用了与栈完全不同的原则,栈是后进先出原则,而队列是先进先出(First In First Out)。

一、队列

     队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。队列中没有元素时,称为空队列。
  队列的数据元素又称为队列元素。在队列中插入一个队列元素称为入队,从队列中删除一个队列元素称为出队。因为队列只允许在一端插入,在另一端删除,所以只有最早进入队列的元素才能最先从队列中删除,故队列又称为先进先出(FIFO—first in first out)线性表。
  我们对队列有了基本的了解,那么我们来看看如何实现队列。其实跟栈的实现极为类似,只是入队和出队的方法稍有不同,那么我们来看看一个完整的队列需要哪些方法:
    1、enqueue(element(s)),入队,向队列尾部添加一个或者多个元素。
    2、dequeue(),出队,移除队列中的第一个元素,也就是队列最前面的元素,并返回该元素。
    3、front(),获取队列最前面的元素,返回队列中第一个元素(最先被添加,也是最先被移除的元素)。队列并不移除该元素。
    4、isEmpty(),判断队列是否不包含任何元素。
    5、size(),返回队列的元素总数。
复制代码
 //声明Queue类
  function Queue() {
      //声明并初始化一个用来存放队列元素的数组。
      let items = [];
      //添加队列元素
      this.enqueue = function (element) {
          items.push(element)
      };
      //移除并返回该队列元素
      this.dequeue = function () {
          return items.shift();
      };
      //获取队列头部元素
      this.front = function () {
          return items[0];
      };
      //判断队列元素是否为空
      this.isEmpty = function () {
          return items.length == 0;
      };

      //获取队列元素个数
      this.size = function () {
          return items.length;
      };
      //打印该队列
      this.print = function () {
          console.log(items.toString())
      };
  }
const queue = new Queue();
console.log(queue.isEmpty()); // outputs true
queue.enqueue('John');
queue.enqueue('Jack');
queue.print(); // John,Jack
queue.enqueue('Camila');
queue.print(); // John,Jack,Camila
console.log(queue.size()); // outputs 3
console.log(queue.isEmpty()); // outputs false
queue.dequeue(); // remove John
queue.dequeue(); // remove Jack
queue.print(); // Camila
复制代码

  上面我们就已经实现了队列这种数据结构,同样的,我们是否可以稍微改造一下,让队列的实现看起来更加优美一点。

复制代码
let Queue = (function () {
      const items = new WeakMap();

      class Queue {
          constructor () {
        //强调一下,这里items是WeakMap类型的数据,而WeakMap是键值对,有专属的set和get方法来获取和设置值,
        //所以这里给this设置了[],即以this为键名,[]为值,所以该方法形成的队列仍旧是对数组的操作 items.set(this,[]); } enqueue(element) { let q = items.get(this);//这里的q就相当于是[] q.push(element); } dequeue() { let q = items.get(this); let r = q.shift(); return r; } front() { return items.get(this)[0]; } isEmpty() { return items.get(this).length == 0; } size() { return items.get(this).length; } print() { console.log(items.get(this)); } } return Queue; })()
复制代码

  其实到这里队列就基本介绍完了,但是感觉实在有点糊弄人啊。所以就把剩下的内容都在这一篇文章写完吧。

二、优先队列
  我们说完了队列,那么我们看看什么是优先队列。普通的队列是一种先进先出的数据结构,元素在队列尾追加,而从队列头删除。在优先队列中,元素被赋予优先级。当访问元素时,具有最高优先级的元素最先删除。优先队列具有最高级先出 (first in, largest out)的行为特征。就像是我们在窗口买票,机场排队,正常来说我们都是依照排队的顺序从队列的最前面开始依次进入,但是有规定老人孩子军人等优先,那么就赋予了该老人(孩子军人)插队的权利。而优先队列,同样就是给特定元素赋予插队(优先级)的权利。我想要入队,并不一定是直接到尾部。而是根据我设定的优先级来插入队列。
  其实优先队列在实现上不同的地方是队列元素的设定和入队方法的不同(这里其实有两种实现方式,一个是按照优先级入列,一个是按照优先级出列,这里我们只用第一种方式实现)。下面我们就看看如何实现优先队列吧。
复制代码
  //声明Queue类
  function PriorityQueue() {
      //声明并初始化一个用来存放队列元素的数组。
      let items = [];
      //创建一个拥有优先级的元素类
      function QueueElement(element,priority) {
          this.element = element;
          this.priority = priority;
      }
      //添加队列元素
      this.enqueue = function (element,priority) {
          let queueElement = new QueueElement(element,priority);
          let added = false;
          //遍历队列元素,1的优先级最高,一次类推,如果当前元素优先级大于items[i],那么就把该元素放在items[i]前面。
          //splice方法的第二的参数如果为0,那么则把第三个参数添加到i前面。
          for(let i = 0; i < items.length; i++) {
              if(queueElement.priority < items[i].priority) {
                  items.splice(i,0,queueElement);
                  added = true;break;
              }
          }
          // 通过added判断是否可以直接把元素入列。
          if(!added) {
              items.push(queueElement);
          }
      };
      //移除并返回该队列元素
      this.dequeue = function () {
          return items.shift();
      };
      //获取队列头部元素
      this.front = function () {
          return items[0];
      };
      //判断队列元素是否为空
      this.isEmpty = function () {
          return items.length == 0;
      };

      //获取队列元素个数
      this.size = function () {
          return items.length;
      };
      //循环打印元素及其优先级“``”是ES6的模板字符串
      this.print = function () {
          for(let i = 0; i < items.length; i++) {
              console.log(`${items[i].element} - ${items[i].priority}`);
          }
      };
  }
const queue = new PriorityQueue();
console.log(queue.isEmpty()); // outputs true

queue.enqueue('zaking',2);
queue.enqueue('linbo',6);
queue.enqueue('queue',5);
queue.enqueue('ada',3);
queue.enqueue('John',1);
queue.enqueue('Jack',2);
queue.enqueue('Camila',3);
queue.enqueue('zak',3);
queue.print(); 
复制代码

  主要的更改在于队列元素的设置和enqueue方法,由于需要为每一个循环队列的元素设置优先级,所以这里稍微更改了一下队列的元素,使其带有两个参数(元素自身和优先级),那么既然要根据不同的优先级来插入队列,所以循环队列的enqueue方法也就需要循环整个队列去判断要插入到哪里。

   其实这个优先队列的实现并不是很好,比如我不传第二优先级参数,那么队列打印的时候该参数就是undefined,而且在不传参数的时候应该默认为最末优先级。大家可以试着去修改一下代码,使其看起来更符合实际。
 
三、循环队列
  除了优先队列以外还有循环队列,循环队列的一个比较容易想象的例子就是击鼓传花游戏,游戏规则就不说了大家小时候都玩过,我们看看如何实现击鼓传花游戏。
复制代码
function hotPotato(nameList, num) {
  const queue = new Queue();
  //把所有的名单(nameList)依次入列
  for (let i = 0; i < nameList.length; i++) {
    queue.enqueue(nameList[i]);
  }

  //声明当前被淘汰的人员名称
  let eliminated = '';
  //如果队列中的元素大于一个,说明还没有最后的赢家,如果只剩下一个,就出列该最后赢家
  while (queue.size() > 1) {
      //循环当前队列num次,把队列头部的“出列元素”再入列。
    for (let i = 0; i < num; i++) {
      queue.enqueue(queue.dequeue());
    }
    //循环结束后,出列当前队列的元素,也就是淘汰者。
    eliminated = queue.dequeue();
    queue.print();
    console.log(eliminated + "被淘汰");
  }

  return queue.dequeue();
}

let names = ["zak","zaking","james","lili","bole","londo","fali"]
console.log(hotPotato(names,7))
复制代码

  上面的方法,每次循环都会依次把头部元素放入到尾部,就实现了一个圈,然后我们以循环结束后,队列最前端的元素视为淘汰,直到最后只剩下一个元素,也就真实的模拟了击鼓传花游戏。

 

http://www.jmk5203.top/
http://www.mug5965.top/
http://www.gtt6107.top/
http://www.cnp6436.top/
http://www.sdx1013.top/
http://www.jwd3113.top/
http://www.qeu2095.top/
http://www.tux4376.top/
http://www.tay3928.top/
http://www.tgq6935.top/
http://www.win4778.top/
http://www.ngh4321.top/
http://www.cqq1459.top/
http://www.fxm1291.top/
http://www.wyz5825.top/
http://www.kbx3827.top/
http://www.tqt8862.top/
http://www.yma5505.top/
http://www.rye6349.top/
http://www.xqs4260.top/
http://www.fjv3790.top/
http://www.wqv1289.top/
http://www.mxz6626.top/
http://www.npl2536.top/
http://www.vme0237.top/
http://www.edr0603.top/
http://www.kft8502.top/
http://www.kwb2561.top/
http://www.dqv1869.top/
http://www.iai9521.top/
http://www.jla2696.top/
http://www.vip1477.top/
http://www.ryc2010.top/
http://www.tpz5308.top/
http://www.gzi6562.top/
http://www.dwf8840.top/
http://www.soq5741.top/
http://www.pud6117.top/
http://www.zrv3166.top/
http://www.ylg5948.top/
http://www.evm5267.top/
http://www.mmc0244.top/
http://www.auk8793.top/
http://www.nbw1542.top/
http://www.oka2713.top/
http://www.txz2284.top/
http://www.amv5754.top/
http://www.ubb2737.top/
http://www.oim9564.top/
http://www.jhg1176.top/
http://www.ehe5445.top/
http://www.vkp0211.top/
http://www.uzy8206.top/
http://www.cnn5986.top/
http://www.nwz4782.top/
http://www.qndfr.org/
http://www.zcshr.org/

java 使用LinkedList模拟一个堆栈或者队列数据结构

java 使用LinkedList模拟一个堆栈或者队列数据结构
  • coderinchina
  • coderinchina
  • 2014-10-29 11:35:25
  • 2409

JavaScript数据结构之队列

队列和栈非常的类似,但是使用了不同的原则,栈是先进后出,而队列是先进先出,即遵循的是FIFO(First In First Out,先来先服务)。队列也可以这样形象地想象成是将数组装到一根管子里,一边...
  • L_in12
  • L_in12
  • 2016-06-27 11:10:16
  • 776

[Lintcode]用栈实现队列

正如标题所述,你需要使用两个栈来实现队列的一些操作。 队列应支持push(element),pop() 和 top(),其中pop是弹出队列中的第一个(最前面的)元素。 pop和top方法都应该返...
  • wutingyehe
  • wutingyehe
  • 2016-02-04 16:39:54
  • 723

c++基本数据结构的类的用法--栈,队列,链表

1.stack类 转自:http://www.169it.com/article/2839007600903800247.html c++ stl栈stack介绍 C++ Stack(堆栈) 是一...
  • xtnc1028
  • xtnc1028
  • 2015-05-28 16:41:05
  • 1063

【数据结构】(面试题)使用两个栈实现一个队列(详细介绍)

使用两个栈实现一个队列思路一:我们设定s1是入栈的,s2是出栈的。入队列,直接压到s1即可出队列,先把s1中的元素倒入到s2中,弹出s2中的栈顶元素;再把s2的剩余元素全部倒回s1中。650) thi...
  • hanjing_1995
  • hanjing_1995
  • 2016-05-30 17:18:28
  • 2981

数据结构—栈和队列的相互模拟

1、两个栈模拟一个队列 栈是LILO,而队列是FIFO,所以可以: 入队,直接进A号栈; 出队,先判断B号栈是否有元素,有元素就直接弹出栈顶即队首,如果B号栈没有元素,则将A号栈的元素顺序弹出并进B号...
  • xwchao2014
  • xwchao2014
  • 2015-05-18 16:00:20
  • 341

用JavaScript来实现队列

队列的定义 队列(Queue)是一种遵从先进先出(First in, first out。简称FIFO)原则的有序集合。 优先队列是队列的修改版。元素的添加与移除是基于优先级别进行的。...
  • maomaolaoshi
  • maomaolaoshi
  • 2017-08-07 17:45:56
  • 639

快速排序的非递归算法(使用队列)

前些天学习了程序栈空间的大小是会有上限的。看来递归的算法永远无法应用到大规模的数据上,毕竟栈空间有限。这几天写了点算法题目,刚好涉及到如何广度优先搜索。想起自己学数据结构的时候就想快排能否以非递归式方...
  • meiboyu
  • meiboyu
  • 2014-01-13 20:07:24
  • 2091

数据结构例程——迷宫问题(用队列)

数据结构例程——表达式求值(用队列)  本文针对数据结构基础系列网络课程(3):栈和队列中第5课时队列的应用-迷宫问题。例:求出从入口到出口的路径 代码:#include #define MaxS...
  • sxhelijian
  • sxhelijian
  • 2015-09-15 11:48:52
  • 7590

C++实现数据结构-队列

最近学了C++,看了下数据结构的东西,这里就跟大家分享一下自己用C++实现队列的一些思想和经验,适合初学者交流学习。 队列分类 队列在数据结构中分为普通队列和环形队列。首先说说普通队列,就是一种类似...
  • CV_YOU
  • CV_YOU
  • 2016-09-19 21:07:47
  • 1376
收藏助手
不良信息举报
您举报文章:用js来实现那些数据结构(队列)
举报原因:
原因补充:

(最多只允许输入30个字)