在上一文章中介绍了什么是栈,如何创建一个栈,栈的链接。队列和栈非常类似。
队列介绍
- 栈遵循的是后进先出(Last In First Out )原则,队列遵循的是先进先出(First In First Out )原则的一组有序的项。队列在尾部添加新元素,并从顶部移除元素。最新添加的元素必须排在队列的末尾。 举一个在生活中常见的栗子(对,我就是叫栗子。哼):
- 中午食堂排队吃饭,第一个人过来排队(在末端添加元素)的人肯定会第一个打到饭,打完饭后他的走啊,给后面的同志腾地儿啊(从顶部删除元素)。
创建队列
我们需要创建一个类来表示一个队列。
constructor() {
this.items = {}; // 存储元素
this.count = 0; // 控制队列大小
this.lowestCount = 0; // 追踪第一个元素
}
}
复制代码
-
首先需要用于存储队列中元素的数据结构。我们可以使用数组,但为了写出一个在获取元素时更高效的数据结构,我们将使用一个对象来存储我们的元素。
-
然后声明一个count属性来帮助我们控制队列的大小,最后由于我们将要从队列前端移除元素,同样需要一个变量来帮助我们追踪第一个元素。因此,声明一个lowestCount变量
-
接下来就是对这个类添加一些队列可用的方法。
- 向队列尾部添加一个新的元素
- 由于items属性是一个对象,因此要向队列中加入一个元素的话。我们要把count变量作为items对象中的键,对应元素作为它的值。最后再让count变量自增。
enqueue(element) { this.items[this.count] = element; // 以count变量作为items对象中的键,对应元素作为它的值 this.count++; // 让count变量自增 } 复制代码- 检查队列是否为空
- 队列后端的值减去队列前端的值如果等于0,他就是空的
isEmpty() { return this.count - this.lowestCount ===0; } 复制代码- 从列表移除元素
- 先是检查队列中是否为空==>如不为空我们将队列头部的值存起来==>移除队列顶部元素==>然后把lowestCount属性自增==>最后再把刚才存起来的元素返回
dequeue() { if (this.isEmpty())return false; // 先是检查队列中是否为空,空的话就不搞了 const result = this.items[this.lowestCount]; // 如不为空我们先将队列头部的值存起 delete this.items[this.lowestCount]; // 移除队列顶部元素 this.lowestCount++; // 然后把lowestCount属性自增 return result; // 最后再把刚才存起来的删除的元素返回 } 复制代码- 计算队列长度
- 队列后端的值减去队列前端的值就是它的长度
size(){ return this.count - this.lowestCount; } 复制代码- 清空队列
- 把这三个值初始化一下就好了
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是本次击鼓传花游戏中的冠军。
复制代码
1万+

被折叠的 条评论
为什么被折叠?



