数据结构——队列

一种受限的数据结构

队列:先进先出

  • 它只允许表的前端(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)
      // }
    }
  }
}

 

posted @ 2026-07-16 11:26  nini-  阅读(7)  评论(0)    收藏  举报