数据结构与算法(二)-队列(queue)

队列(queue)结构

一、介绍

队列是一种特殊的线性表,生活中类似队列结构的场景:

  • 排队:比如在电影院,商场,甚至是厕所排队。
  • 优先排队的人,优先处理。 (买票、结账、WC)。

如图所示:

队列的限制

  • 先进先出 (FIFO:First In First Out)

  • 只允许在表的前端(front)进行删除操作

  • 只允许在表的后端(rear)进行插入操作

如图所示:

二、程序中的队列

  • 打印队列:计算机打印多个文件的时候,需要排队打印
  • 线程队列:当开启多线程时,当新开启的线程所需的资源不足时就先放入线程队列,等待 CPU 处理

三、队列的实现

队列有两种实现方式,这里就基于数组方式实现了

  • 基于数组实现
  • 基于链表实现

队列常见的操作

  • enqueue(element) 向队列尾部添加一个(或多个)新的项
  • dequeue() 移除队列的第一(即排在队列最前面的)项,并返回被移除的元素
  • front() 返回队列中的第一个元素——最先被添加,也将是最先被移除的元素。队列不做任何变动(不移除元素,只返回元素信息与 Map 类的 peek 方法非常类似)
  • isEmpty() 如果队列中不包含任何元素,返回 true,否则返回 false
  • size() 返回队列包含的元素个数,与数组的 length 属性类似
  • toString() 将队列中的内容,转成字符串形式

代码实现

1.普通队列
function Queue() {
  this.items = [];

  // 1.将元素加入队列
  Queue.prototype.enqueue = function (element) {
    return this.items.push(element);
  };

  // 2.从队列中删除元素
  Queue.prototype.dequeue = function () {
    return this.items.shift();
  };

  // 3.查看前端的元素
  Queue.prototype.front = function () {
    return this.items[0];
  };

  // 4.查看队列是否为空
  Queue.prototype.isEmpty = function () {
    return this.items.length === 0;
  };

  // 5.查看队列元素个数
  Queue.prototype.size = function () {
    return this.items.length;
  };

  // 6.toString方法
  Queue.prototype.toString = function () {
    // 返回格式如: 10 20 30 等
    var resString = "";
    for (var i = 0; i < this.items.length; i++) {
      resString += this.items[i] + " ";
    }
    return resString;
  };
}
测试代码
var q = new Queue();
q.enqueue("10");
q.enqueue("20");
q.enqueue("30");
console.log(q.items); // [ '10', '20', '30' ]

q.dequeue();
console.log(q.items); // [ '20', '30' ]

console.log(q.front()); // 20
console.log(q.isEmpty()); // false
console.log(q.size()); // 2
console.log(q.toString()); // 20 30
2.优先级队列

优先级队列,在队列的基础上,增加优先级

其实就是在元素入队时根据传入的优先级,找到合适的位置,并插入

function PriorityQueue() {
  // 内部类 也可以用对象存放
  function QueueElement(element, priority) {
    this.element = element;
    this.priority = priority;
  }

  this.item = [];

  // 1.将元素加入队列
  PriorityQueue.prototype.enququ = function (element, priority) {
    var queueElement = new QueueElement(element, priority);
    // 如果数组为空,将直接push
    if (this.item.length === 0) {
      this.item.push(queueElement);
    } else {
      var added = false;
      for (var i = 0; i < this.item.length; i++) {
        // 若发现优先级比较大
        if (queueElement.priority < this.item[i].priority) {
          // 插入进去
          this.item.splice(i, 0, queueElement);
          added = true;
          break;
        }
      }

      // 若没有执行过插入,说明优先级比较小,直接push
      if (!added) {
        this.item.push(queueElement);
      }
    }
  };

  // 2.从队列中删除元素
  PriorityQueue.prototype.dequeue = function () {
    return this.items.shift();
  };

  // 3.查看前端的元素
  PriorityQueue.prototype.front = function () {
    return this.items[0];
  };

  // 4.查看队列是否为空
  PriorityQueue.prototype.isEmpty = function () {
    return this.items.length === 0;
  };

  // 5.查看队列元素个数
  PriorityQueue.prototype.size = function () {
    return this.items.length;
  };

  // 6.toString方法
  PriorityQueue.prototype.toString = function () {
    // 返回格式如: 10 20 30 等
    var resString = "";
    for (var i = 0; i < this.items.length; i++) {
      resString += this.items[i] + " ";
    }
    return resString;
  };
}

四、应用

1.击鼓传花

const Queue = require("./queue");

/**
 * 击鼓传花游戏规则:
 * 几个朋友一起玩一个游戏,围成一圈,开始数数,数到某个数字的人自动淘汰
 * 最后剩下的这个人会获得胜利,请问:最后胜利者原来在哪一个位置上
 */
let names = ["小明", "小红", "小亮"];
function passGame(nameList, stopNum = 1) {
  let q = new Queue();
  for (const item of nameList) {
    q.enqueue(item);
  }

  while (q.size() > 1) {
    for (let i = 0; i < stopNum - 1; i++) {
      q.enqueue(q.dequeue());
    }
    q.dequeue();
  }
  console.log("最后剩下的人是:", q.front()); // 最后剩下的人是: 小红
  return nameList.indexOf(q.front()); //返回对应的位置
}

console.log(passGame(names, 3)); // 1

2.最近的请求次数

var RecentCounter = function () {
  this.queue = [];
};

/** 
 * @param {number} t
 * @return {number}
 */
RecentCounter.prototype.ping = function (t) {
  this.queue.push(t)
  // 将3000ms之前的数据,踢出队列
  while (this.queue[0] < t - 3000) {
    this.queue.shift()
  }
  // 队列中剩下的元素个数就是最近的请求次数
  return this.queue.length
};

往期精彩文章

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一个爱编程的男孩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值