五分钟带你熟悉队列结构

171 阅读3分钟

一、什么是队列结构

前面一篇已经介绍了栈结构,我们对于栈结构已经有了很好的认识。栈结构的特点是'先进后出',而队列的特点正好相反是'先进先出'。

对于队列的实现,我们可以用数组或者是链表,接下来介绍一下数组的实现方法。话不多说,直接上代码。

class Queue {
  constructor() {
    this.queue = [];
  }
  // 进队列
  enqueue(element) {
    this.queue.unshift(element);
  }
  // 出队列
  dequeue() {
    this.queue.pop();
  }
  // 查看队列的大小
  size() {
    return this.queue.length;
  }
  // 查看队列是不是空的
  isEmpty() {
    return this.queue.length === 0;
  }
  // 返回队列第一个元素
  front() {
    return this.queue[this.queue.length - 1];
  }
}

在看过上一篇[数组实现栈结构](js实现栈结构 - 掘金 (juejin.cn))后,用数组实现队列结构应该是很简单地。

让我们测试一下刚刚写的代码吧

// 实例化一个队列对象
const queue = new Queue();

// 往队列中添加元素
queue.enqueue(1);
queue.enqueue(2);
queue.enqueue(3);
queue.enqueue(4);

console.log(queue.size());  //  4
queue.dequeue();            
console.log(queue.front()); // 2
console.log(queue.isEmpty()); // false

看来是没有什么bug。嘿嘿嘿。。。

接着,让我们来看一个非常金典的问题

二、 击鼓传花

简介, 有一群小朋友,围成一圈,席地而坐,从第一位小朋友开始传花,在指定几次鼓声后,手里有花的小朋友需要进行节目表演。表演完后,小朋友出圈,继续传花。求最后的小朋友是谁?

是不是很熟悉?这不就是约瑟夫环吗?如果用队列的方式,你会怎么实现。

思考实现方式

  1. 首先创建一个队列实例
  2. 往队列里放入元素
  3. 封装功能函数,传入队列和指定淘汰索引
  4. 循环遍历。定义一个count记录当前数值,当count不等于指定数字时,元素出队列,把出队列的元素再入队列。
  5. 当count等于指定数字时,出队列
  6. 当队列的长度为1时,停止循环,返回最后的元素

有了思考,我们可以落实到代码中。

function passGame(nameList, num) {
  // 创建队列
  const queue = new Queue();
  // 数据入队列
  for (let i = 0; i < nameList.length; i++) {
    queue.enqueue(nameList[i]);
  }

  // 留下最后一人
  while (queue.size() > 1) {
    // 遍历到约定的num之前一位
    for (let i = 0; i < num - 1; i++) {
      // 把队列的头部重新入队列
      queue.enqueue(queue.dequeue());
    }
    // 删除num元素
    queue.dequeue();
  }

  console.log("最后留下的人是:", queue.front());
  console.log("索引是:", nameList.indexOf(queue.front()));
}

好了,恭喜你,约瑟夫环问题已经被解决

三、优先级队列

什么是优先级队列呢?

顾名思义,就是按照优先级排列的队列。

那我们怎么实现优先级队列呢?

我们可以发现,优先级队列与普通的队列不同之处在于元素的入队列。在优先级队列中,我们要更具元素的优先级,进行优先级排序,然后插入。

思考

  1. 当队列为空时,直接插入
  2. 队列不为空时,遍历队列,查找有没有优先级大于要插入元素的优先级
  3. 如果有,则在优先级大的前面插入
  4. 没有,则直接在队列后插入

好了,我们来看一下代码怎么实现

enqueue(element, priorty) {
    // 1. 如果队列为空
    if (this.isEmpty()) {
      this.queue.unshift({
        element,
        priorty,
      });
    } else {
      // 2. 有比放入的优先级大的
      for (let i = 0; i < this.queue.length; i++) {
        if (priorty < this.queue[i].priorty) {
          this.queue.splice(i, 0, { element, priorty });
          return;
        }
      }
      // 3. 没有比放入的优先级大
      this.queue.push({ element, priorty });
    }
  }

这样,优先级队列的插入方法就实现了,其他方法和普通的队列方式一致。

感谢阅读,觉得有帮助可以点点赞,非常感谢!