数据结构之队列和优先级队列
程序员文章站
2022-03-12 17:11:04
...
基础数据结构
队列机构 Queue
- 先进先出 FIFO(first In First Out)
- 允许在前端(front)删除,允许在后端(rear)插入
- 特殊:优先级队列
队列相当于一个集合或者队列,一个任务集合;
特点:先进先出(谁先进来谁就在队列的头部,就能先出去),只能允许末尾添加,只能允许开头删除。
自己实现队列结构
自己实现队列结构要先准备一个容器,准备好容器后要有一个从末尾进队列(enter)的方法和一个从开头出队列(leave)的方法,获取队列长度(length),队列信息(value)
function Queue(){
//创建一个堆列的容器
this.container = [];
};
Queue.prototype = {
constructor:Queue,
//进入队列 element进入队列,放到数组(队列容器)末尾
enter:function enter(element){
this.container.push(element)
},
//移除队列
leave :function leave(){
if(this.container.length === 1) return;
return this.container.shift();
},
//查看队列长度
size: function size(){
return this.container.length;
},
//查看队列内容
value:function value(){
//深度克隆是为了保证后期外面接收到的结果不论如何操作都不会影响内部结果
return JSON.parse(JSON.stringify(this.container));
}
};
//创建一个队列
let qe = new Queue();
qe.enter(1);
qe.enter(2);
qe.enter(3);
qe.enter(4);
qe.enter(5);
qe.leave();
console.log(qe);//[2, 3, 4, 5]
面试题:击鼓传花游戏
N个人一起玩游戏,围成一圈,从1开始数,数到M的人淘汰;最后剩下的人会取得胜利,问最后剩下的是原来的那一位?
- 把参加游戏的人依次进入到队列中
- 从头开始喊数:不是关键数,先移除再进入队列的末尾;数到关键数,则把它移除。
/*
n:参加游戏人数
m:关键数
*/
function game(n, m){
//创建存放队列的容器
let qe = new Queue();
//先把人依次放到队列当中
for(var i = 1; i<= n; i++){
qe.enter(i);
}
// 从头开始喊数:不是关键数,先移除再进入队列的末尾;数到关键数,则把它移除。
while(qe.size() > 1){
for(let i = 0;i < m-1; i++){
qe.enter(qe.leave());
};
qe.leave();
}
return qe.value()[0];
};
let res = game(6, 4);
console.log(res); // 5
优先级队列
每个新增的元素不是放在队列的末尾,而是按照指定的优先级放置到指定的位置
每个元素都有自己的优先级
一个正常的队列,存的时候只能存到末尾,移除的时候只能移除开头的元素;
优先级队列,加入队列的时候,每一个元素都有一个自己的优先级,不一定都放到末尾,而是按照优先级优先放到指定位置(就像生活中老幼病残孕优先,军人优先一样),移除的时候也是优先移除。
自己封装一个优先级队列
class Queue {
//创建一个堆列的容器
container = [];
//进入队列 element进入队列,priority 优先级,默认都是0,数值越大,优先级越高
enter(element, priority = 0) {
let obj = {
value: element,
priority: priority
};
//优先为默认的0,直接添加到数组的末尾
if (priority === 0) {
this.container.push(obj);
return;
};
//指定优先级需要从最后一项依次来比较
let flag = false;
for (let i = this.container.length - 1; i >= 0; i--) {
let item = this.container[i];
//当前项优先级大于或者等于插入项的时候,把插入项插到当前项的后面
if (item.priority >= priority) {
this.container.splice(i + 1, 0, obj);
flag = true;
break;
};
};
//没有比插入项大的,则插入到数组的开头。
!flag ? this.container.unshift(obj) : null;
};
//移除队列
leave() {
if (this.container.length === 1) return;
return this.container.shift();
};
//查看队列长度
size() {
return this.container.length;
};
//查看队列内容
value() {
return JSON.parse(JSON.stringify(this.container));
}
}
let qe = new Queue();
qe.enter(12, 9);
qe.enter(1, 1);
qe.enter(11, 0);
qe.enter(2, 4);
qe.enter(4);
console.log(qe)
/*
Queue {container: Array(5)}
打开后:=>
container: Array(5)
0: {value: 12, priority: 9}
1: {value: 2, priority: 4}
2: {value: 1, priority: 1}
3: {value: 11, priority: 0}
4: {value: 4, priority: 0}
length: 5
__proto__: Array(0)
__proto__: Object
*/