队列:受限的线性结构
定义:是一种运算受限的线性表
规则:
队列遵循先进先出
先进先出First in first out FIFO
队列的详解:
1.当队列中没有元素,或者只有一个元素时,队首与队尾指向的都是同一个元素:
2.当元素1,元素2依次入队,队首指向元素1,而队尾指向元素2
封装队列(es6):
class Queue{
// 封装队列结构
constructor(){
this.item=[]
}
// 1.入队
enqueue(ele){
this.item.push(ele)
}
// 2.出队
dequeue(){
return this.item.shift()
}
// 3.查看队首元素
front(){
return this.item[0]
}
// 4.查看队列是否为空
isEmpty(){
return this.item.length==0
}
// 5.查看队列中元素的个数
size(){
return this.item.length
}
}
优先级队列:
为什么要封装优先级队列:
- 因为每个线程处理的任务重要性不同, 我们可以通过优先级的大小, 来决定该线程在队列中被处理的次序.
优先级思想:
- 我们知道, 普通的队列插入一个元素, 数据会被放在后端. 并且需要前面所有的元素都处理完成后才会处理前面的数据.
- 但是优先级队列, 在插入一个元素的时候会考虑该数据的优先级.(和其他数据优先级进行比较)
- 比较完成后, 可以得出这个元素正确的队列中的位置. 其他处理方式, 和队列的处理方式一样.
- 也就是说, 如果我们要实现优先级队列, 最主要是要修改添加方法. (当然, 还需要以某种方式来保存元素的优先级)
封装优先级队列(es6):
代码分析:
在插入新的元素时, 有如下情况下考虑:
-
根据新的元素先创建一个新的Node对象.
-
如果元素是第一个被加进来的, 那么不需要考虑太多, 直接加入数组中即可.
-
如果是后面加进来的元素, 需要和前面加进来的元素依次对比优先级.
-
一旦优先级, 大于某个元素, 就将该元素插入到元素这个元素的位置. 其他元素会依次向后移动.
-
如果遍历了所有的元素, 没有找到某个元素被这个新元素的优先级低, 直接放在最后即可.
<script> // 封装一个构造函数,用于保存元素和元素的优先级 class Node { constructor(ele,priority) { this.ele = ele this.priority =priority } } class PriorityQueue { constructor() { this.item = [] } // 添加元素的方法 enqueue(ele, priority) { // 创建新节点 或者let newnode={data:ele,priority:priority} let newnode = new Node(ele, priority) if (this.item.length == 0) { // 队列是一个空队列,就不用比较优先级,元素直接入队 this.item.push(newnode) } else { // 非空队列 // 元素是否被添加到队列中 let isAdd = false; for (let i = 0; i < this.item.length; i++) { // 依次比较优先级 if (newnode.priority < this.item[i].priority) { // 注意:我们这里数字越小,优先级越高 // 新节点的优先级高于队列中元素的优先级 // 将新节点插入队列中 // 插入到它优先级高于的那个元素的前面 // splice(start,length)方法: 删除元素,并向数组添加新元素。 this.item.splice(i, 0, newnode); isAdd = true break; } } // 循环遍历结束都没有优先级比新节点要小的元素时,直接添加到队列的最后 if (!isAdd) { this.item.push(newnode) } } } // 出队 dequeue(){ return this.item.shift() } // 获取前端的元素 front(){ return this.item[0] } // 查看元素是否为空 isEmpty(){ return this.item.length=00 } // 获取元素的个数 size(){ return this.item.length } }
相关设计代码:
1.击鼓传花:
- 几个朋友一起玩一个游戏, 围成一圈, 开始数数, 数到某个数字的人自动淘汰。
- 最后剩下的这个人会获得胜利, 请问最后剩下的是原来在哪一个位置上的人?
图解: 1.
3.
4.
5.
6.
7.
9.
10.所以到最后队列中只剩下了鲨鱼辣椒
正确代码:
<script src="Queue.js"></script>
<script>
function jigu(ele,num){
// 创建一个队列
var queue=new Queue()
// 将数组中所有元素入队
ele.forEach((el,index) => {
queue.enqueue(el)
});
let index=1
// 找最后一个人
while(queue.size()>1){
// for(var i=0;i<num;i++){
// // 将所有不等于3的数出队,又入队
// queue.enqueue( queue.dequeue())
// }
// // 数数等于3,出队,不重新入队
// queue.dequeue()
// 上面这个代码是错误的,当i>num时,会在一次循环中移出两次元素
// 因为queue.dequeue()重复了两次
if (index >= num) {
// 将index=num的元素移出队列
queue.dequeue()
// 再让index继续从1开始数数
index = 1
}
queue.enqueue(queue.dequeue())
index++
}
// 最后一个人
var endname=queue.front()
console.log(endname);
// 在队列中的位置
return ele.indexOf(endname)
}
var arr=["鲨鱼辣椒","蜻蜓队长","蟑螂恶霸","金龟次郎","蝎子莱莱","铁甲小宝"]
jigu(arr,3)
</script>
错误代码:
while循环中,当i>num时,会在一次循环中移出两次元素,因为queue.dequeue()重复了两次
<script src="Queue.js"></script>
<script>
function jigu(ele,num){
var queue=new Queue()
// 将数组中所有入队
ele.forEach((el,index) => {
queue.enqueue(el)
});
// 找最后一个人
while(queue.size()>1){
for(var i=0;i<num;i++){
// 将所有不等于3的数出队,又入队
queue.enqueue(queue.dequeue())
}
// 数数等于3,出队,不重新入队
queue.dequeue()
}
// 最后一个人
var endname=queue.front()
console.log(endname);
// 在队列中的位置
return ele.indexOf(endname)
}
var arr=["鲨鱼辣椒","蜻蜓队长","蟑螂恶霸","金龟次郎","蝎子莱莱","铁甲小宝"]
jigu(arr,3)
</script>