队列

在上一文章中介绍了什么是栈,如何创建一个栈,栈的链接。队列和栈非常类似。

队列介绍

  • 栈遵循的是后进先出(Last In First Out )原则,队列遵循的是先进先出(First In First Out )原则的一组有序的项。队列在尾部添加新元素,并从顶部移除元素。最新添加的元素必须排在队列的末尾。 举一个在生活中常见的栗子(对,我就是叫栗子。哼):
    • 中午食堂排队吃饭,第一个人过来排队(在末端添加元素)的人肯定会第一个打到饭,打完饭后他的走啊,给后面的同志腾地儿啊(从顶部删除元素)。

创建队列

我们需要创建一个类来表示一个队列。

    constructor() {
        this.items = {}; // 存储元素
        this.count = 0; // 控制队列大小
        this.lowestCount = 0; // 追踪第一个元素
    }
}
复制代码
  • 首先需要用于存储队列中元素的数据结构。我们可以使用数组,但为了写出一个在获取元素时更高效的数据结构,我们将使用一个对象来存储我们的元素。

  • 然后声明一个count属性来帮助我们控制队列的大小,最后由于我们将要从队列前端移除元素,同样需要一个变量来帮助我们追踪第一个元素。因此,声明一个lowestCount变量

  • 接下来就是对这个类添加一些队列可用的方法。

    1. 向队列尾部添加一个新的元素
    • 由于items属性是一个对象,因此要向队列中加入一个元素的话。我们要把count变量作为items对象中的键,对应元素作为它的值。最后再让count变量自增。
    enqueue(element) {
        this.items[this.count] = element; // 以count变量作为items对象中的键,对应元素作为它的值
        this.count++; // 让count变量自增
    }
    复制代码
    1. 检查队列是否为空
    • 队列后端的值减去队列前端的值如果等于0,他就是空的
    isEmpty() {
        return this.count - this.lowestCount ===0;
    }
    复制代码
    1. 从列表移除元素
    • 先是检查队列中是否为空==>如不为空我们将队列头部的值存起来==>移除队列顶部元素==>然后把lowestCount属性自增==>最后再把刚才存起来的元素返回
    dequeue() {
        if (this.isEmpty())return false; // 先是检查队列中是否为空,空的话就不搞了
        const result = this.items[this.lowestCount]; // 如不为空我们先将队列头部的值存起
        delete this.items[this.lowestCount]; // 移除队列顶部元素
        this.lowestCount++; // 然后把lowestCount属性自增
        return result; // 最后再把刚才存起来的删除的元素返回
    }
    复制代码
    1. 计算队列长度
    • 队列后端的值减去队列前端的值就是它的长度
    size(){
        return this.count - this.lowestCount;
    }
    复制代码
    1. 清空队列
    • 把这三个值初始化一下就好了
    clear() {
        this.items= {};
        this.count = 0;
        this.lowestCount = 0;
    }
    复制代码
  • 使用Queue类

const queue = new Queue(); // 初始化
console.log(queue.isEmpty()) // 此时为true
queue.enqueue('John'); // {0:John}
queue.enqueue('Jack'); // {0:John,1:Jack}
console.log(queue.size()); // 输出2
console.log(queue.isEmpty()) // 此时为false
queue.dequeue(); // {1:Jack}
复制代码

这便是一个简单的队列啦

循环队列--击鼓传花游戏

  • 循环队列是队列的一种修改版本,我们用循环队列来做一个例子叫做:击鼓传花游戏。在这个游戏中,孩子们围成一个圆圈,把花尽快的传递给旁边的人。某一时刻传花停止,这个时候花在谁的手里,谁就退出圆圈,结束游戏。重复这个游戏,直到只剩下一个孩子(胜者)。
const hotPotato=(elementsList, num)=> {
  const queue = new Queue();
  const eliminatedList = []; // 用来存储被淘汰的列表
  for (let i = 0; i < elementsList.length; i++) { // 先把元素加入到队列中
    queue.enqueue(elementsList[i]);
  }

  while (queue.size() > 1) {  // 这是重点!!!只要队列的长度不是一,也就是未分出胜负,就继续循环
    for (let i = 0; i < num; i++) { // 给定一个数字,然后迭代循环,从队列开头移除一个,再把它添加到队列末尾
      queue.enqueue(queue.dequeue());
    }
    eliminatedList.push(queue.dequeue());// 当循环到给定的数字后,删除掉这个元素,然后添加到eliminatedList中
  }

  return {
    eliminated: eliminatedList, // 依次淘汰的所有元素集合
    winner: queue.dequeue() // 最后只剩下一个元素时,它就是胜利者
  };
}
复制代码
const names = ['John', 'Jack', 'Camila', 'Ingrid', 'Carl'];
const result = hotPotato(names, 7);

result.eliminated.forEatch(name => {
    consoel.log(`${namn}`在击鼓传花游戏中被淘汰。)
})

console.log(`恭喜${result.winner}是本次击鼓传花游戏中的冠军`)
以上算法的输出如下:

// Camila在击鼓传花游戏中被淘汰。
// Jack在击鼓传花游戏中被淘汰。
// Carl在击鼓传花游戏中被淘汰。
// Ingrid在击鼓传花游戏中被淘汰。
// 恭喜John是本次击鼓传花游戏中的冠军。
复制代码

转载于:https://juejin.im/post/5cff9a49f265da1b5f264ccb

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值