数据结构——队列
一种受限的数据结构
队列:先进先出
- 它只允许表的前端(front)进行删除操作
- 以及在表的后端(rear)进行插入操作
生活举例:比如排队
队列的应用:
- 打印队列
- 文档的打印是按照次序依次放入打印队列中的
- 再从打印队列中取出文档,优先放入的文档优先被取出,以此类推,直到队列中不再有新的文档
- 线程队列
- 多线程并行开发时,需要使用线程队列,防止大量的线程同时运行处理任务(占用过多资源)
- 线程队列会依次启动线程,并处理对应的任务
队列常见操作:
- enqueue(element):向队列尾部添加一个(或多个)新的项
- dequeue():移除队列的第一个项,并返回被移除的元素
- front():返回队列中第一个元素——最先被添加,也将是最先被移除的元素,队列不做任何变动(不移除元素,只返回信息,和栈stack的peek方法非常相似)
- isEmpty():如果队列中不包含任何元素,返回true,否则返回false
- size():返回队列包含的元素个数,与数组的length属性类似
- toString():将队列中的内容转换成字符串
队列的实现:基于数组实现、基于链表实现
基于数组实现:
// 封装队列类 class Queue{ // 属性 constructor() { this.items = [] } // 方法 // 将元素从尾部加入到队列中 enQueue(element) { this.items.push(element) } // 移除第一个元素,并返回被移除的元素 deQueue() { this.items.shift() } // 返回队列中第一个元素,但不移除 front() { return this.items[0] } // 判断队列是否为空,空返回true,否则返回false isEmpty() { return this.items.length === 0 } // 返回队列中包含的元素个数 size() { return this.items.length } // 将队列内容转换为字符串 toString() { // return this.items.join("") let resultString = '' for (let i = 0; i < this.items.length; i++) { resultString += this.items[i] + "" } return resultString } }
队列的使用:
// 使用 const queue = new Queue() queue.enQueue('abc') queue.enQueue('bbb') queue.enQueue('dda') queue.enQueue('mba') console.log(queue, 'queue'); queue.deQueue() queue.deQueue() console.log(queue, 'queue'); console.log(queue.front()); console.log(queue.isEmpty()); console.log(queue.size());
案例:击鼓传花
详细说明:
- 几个朋友一起玩一个游戏,围成一圈,开始数数,数到某个数字的人自动淘汰
- 最后剩下的这个人会获得胜利,请问最后剩下的是原来在哪个位置上的人
- 封装一个基于队列的函数
- 参数:所有参与人的姓名,基于的数字
- 结果;最终剩下的一人的姓名
思路:循环找对应数字位置上的人,然后移除
如果不是对应数字上的人,将其放到队尾,依次往队尾移动,当遇到对应数字上的人时将其从首位移除
function flower(arr, num=5) { // 1.创建一个队列结构 const queue = new Queue() // 2.将所有人依次加入到队列中 for (let i = 0; i < arr.length; i++) { queue.enQueue(arr[i]) } // 3.开始数数,不是num时重新加入到队列的末尾,如果是num数字时将其从队列中删除 let a = 0 while(queue.size() > 1) { if(a !== num - 1) { // 3.1 num数字之前的人重新放到队列的末尾 queue.enQueue(queue.deQueue()) a++ } else { // 3.2 num对应的这个人直接从队列中删除 queue.deQueue() a = 0 } } return arr.indexOf(queue.front()) }
优先队列
普通队列在插入元素时,数据会被放在队列末尾,需要前面的数据都处理完成后才会处理该数据
优先队列就是在插入一个元素时会考虑该数据的优先级,和其他数据进行优先级比较,得出该元素在队列中的正确位置
特点:每个元素都不再只是一个数据,还得包含该数据的优先级
应用:登机排队:头等舱比经济舱优先级高
计算机中,可以根据优先级队列来重新排序队列中的任务,比如每个线程处理的任务重要性不同,可以通过优先级大小决定该线程在队列中被处理的次序
队列的实现:
// 封装优先级队列 class PriorityQueue { // ES5的内部类,在ES6中使用静态私有内部类的方式实现,#表示私有属性 // 内部通过PriorityQueue.#PriorityElement()访问 static #QueueElement = class { constructor(element, priority) { this.element = element this.priority = priority } } // 封装属性 constructor() { this.items = [] } // 实现插入方法 enqueue(element, priority) { // 创建queueElement对象 const queueElement = new PriorityQueue.#QueueElement(element, priority) if (this.items.length === 0) { this.items.push(queueElement) } else { // 二分查找法 let start = 0 let end = this.items.length - 1 let mid = Math.floor((start + end) / 2) let flag = false while (!flag && start <= end) { if (this.items[mid].priority < priority) { if (mid === this.items.length - 1) { this.items.push(queueElement) flag = true } else { start = mid + 1 mid = Math.floor((start + end) / 2) } } else if (this.items[mid].priority > priority && mid > 0) { if (this.items[mid - 1].priority < priority) { this.items.splice(mid, 0, queueElement) flag = true } else { end = mid - 1 mid = Math.floor((start + end) / 2) } } else { this.items.splice(mid, 0, queueElement) flag = true } } // let added = false // for (let i = 0; i < this.items.length; i++) { // if (priority < this.items[i].priority) { // this.items.splice(i, 0, queueElement) // added = true // break // } // } // if (!added) { // this.items.push(queueElement) // } } } }

浙公网安备 33010602011771号