队列结构
- 受限的线性结构
- 之前我们总结了:栈结构
- 并且已经知道这种受限的数据结构对于解决某些特定的问题,会有特别的效果
- 这面文章,介绍了另外一个受限的数据结构:队列
- 队列的结构:
- 满足先进先出的一种结构
- 受限之处:只允许在表的前端进行删除操作,表的后端进行插入操作
- 抽象比喻:栈就是树立的杯子,而队列就是横着的管道
- 队列的应用:
- 打印队列:这些文档会按照次序放入,优先的放入,优先的被取出
- 线程队列:在开发中,为了让任务可以并行处理,通常会开启多个线程,但是我们不能让大量的线程同时运行处理(占用过多资源)。这个时候,如果有需要开启线程处理任务的话,就会使用线程队列,线程队列会依照次序来启动线程,并且处理任务
队列类的创建和常见操作
- 队列的实现和栈一样,有两种方案
- 基于数组实现
- 基于链表实现
// 封装队列
function Queue() {
//属性
this.items = []
//方法
// 1.将元素加入到队列中
Queue.prototype.enqueue = function (element) {
this.items.push(element)
}
// 2.从队列中删除前端元素
Queue.prototype.dequeue = function () {
return this.items.shift()
}
// 3.查看前端元素
Queue.prototype.front = function () {
return this.items[0]
}
// 4.判断队列是否为空
Queue.prototype.isEmpty = function () {
return this.items.length == 0
}
// 5.获取队列中元素的个数
Queue.prototype.size = function () {
return this.items.length
}
// 6.toString方法
Queue.prototype.toString = function () {
//20 10 12 8 7
let resultString = ''
for (let i = 0; i < this.items.length; i++) {
resultString += this.items[i] + ''
}
return resultString
}
}
//使用队列
var queue = new Queue()
// 验证使用
queue.enqueue('abc')
queue.enqueue('cba')
queue.enqueue('nba')
queue.enqueue('mba')
alert(queue)
queue.dequeue()
alert(queue)
//....其他方法
击鼓传花算法面试题
击鼓传花规则
- 几个朋友一起玩一个游戏,围城一圈,开始数数,数到某个数字的人自动淘汰
- 最后剩下的这个人会获得胜利,请问最后剩下的是原来哪个位置上的人
- 封装一个基于队列的函数:
- 参数:所有参与人的姓名,基于的数字
- 结果:最终剩下的一个人的姓名
- 思路:将这几个人依此加入队列,然后将一个一个取出,每个取出的时候,就将其放入尾部,取出时,如果符合要求,就剔除
代码实现
//面试题,击鼓传花(使用了上面封装的队列类)
function passGame(namelist, num) {
//1.创建一个队列结构
var queue = new Queue
//2.所有人依此加入队列
for (let i = 0; i < namelist.length; i++) {
queue.enqueue(namelist[i])
}
//3.开始数数字
while (queue.size() > 1) {
//不是num的时候,重新加入到末尾,是num的时候,将其从队列中删除
//3.1 num数字之前的人,依此放到末尾去
for (let i = 0; i < num - 1; i++) {
//先删除前端元素,再添加到尾部
queue.enqueue(queue.dequeue())
}
//3.2 num对应的这个人,直接从队列中删除掉
//因为num对应的前面的人都放到后面去了,所以现在前端就是num对应的那个人
queue.dequeue()
}
//获取最终剩下的那个人
//获取最终剩下的那个人再原来的数组中是第一个位置
var endName = queue.front()
return (namelist.indexOf(endName)+1)+':'+endName
}
//测试击鼓传花
names =['lili','lucy','tom','lilei','hy']
console.log(passGame(names, 3))
优先级队列
- 优先级队列:再插入一个元素的时候会考虑该数据的优先级,而不是直接插入
- 和其他数据优先级进行比较
- 比较完成后,可以得出这个元素再队列中正确的位置
- 其他处理方式,和基本队列的处理方式一样
- 优先级队列主要考虑的问题:
- 每个元素不再只是一个数据,而且还包含数据的优先级
- 再添加方式中,根据优先级放入正确的位置
- 优先级队列的应用:
- 登机顺序:头等舱和商务舱的优先级顺序
优先级队列的实现
-
实现优先级队列相对队列主要有两仿麦呢的考虑:
- 1.封装元素和优先级放在一起(可以封装一个新的构造函数)
- 2.添加元素时,将新的插入元素的优先级和队列中已经存在的元素优先级进行比较,以获得自己正确的位置
-
1.初步结构封装:
//封装优先级队列 function PrioritQueue(){ //在封装一个类 //类似java中的内部类,外部传入的两个数,但是内部对这两个数时有封装的 function QueueElement(element,priorit){ this.element = element this.priorit = priorit } //封装属性 this.items = [] //实现插入方法 PrioritQueue.prototype.enqueue=function(element,priorit){ //1.先创建QueueElement对象 var queueElement = new QueueElement(element,priorit) } }
-
2.优先级队列数据结构实现:
//封装优先级队列 function PrioritQueue() { //在封装一个类 //类似java中的内部类,外部传入的两个数,但是内部对这两个数时有封装的 function QueueElement(element, priorit) { this.element = element this.priorit = priorit } //封装属性 this.items = [] //实现插入方法 PrioritQueue.prototype.enqueue = function (element, priorit) { //先创建QueueElement对象 var queueElement = new QueueElement(element, priorit) //判断队列是否为空 if (this.items.length == 0) { //如果为空,则能直接插入 this.items.push(queueElement) } else { let added = false for (let i = 0; i < this.items.length; i++) { if (queueElement.priorit < this.items[i].priorit) { this.items.splice(i, 0, queueElement) added = true break } } if (!added) { this.items.push(queueElement) } } } //(插以外,其他的操作与普通队列相同) // 2.从队列中删除前端元素 PrioritQueue.prototype.dequeue = function () { return this.items.shift() } // 3.查看前端元素 PrioritQueue.prototype.front = function () { return this.items[0] } // 4.判断队列是否为空 PrioritQueue.prototype.isEmpty = function () { return this.items.length == 0 } // 5.获取队列中元素的个数 PrioritQueue.prototype.size = function () { return this.items.length } // 6.toString方法 PrioritQueue.prototype.toString = function () { //20 10 12 8 7 let resultString = '' for (let i = 0; i < this.items.length; i++) { resultString += this.items[i].element + '-' +this.items[i].priorit+ ' ' } return resultString } } // 测试代码 var pq = new PrioritQueue() //enqueue方法 pq.enqueue('abc',111) pq.enqueue('cba',200) pq.enqueue('nba',50) pq.enqueue('nba',66) console.log(pq)