数据结构--优先级队列

942 阅读4分钟

什么是优先级队列

优先级队列(Queue):优先级队列也是队列的一种,在优先级队列中,元素被赋予了优先级,当访问队列中的元素时,高优先级的元素最先被访问。

优先级队列主要考虑两个问题:

  • 队列中的数据不再是单个数据还要包括优先级。
  • 添加数据的过程中根据优先级添加到对应的位置。

如下图:

Priority

优先级队列的常见操作

主要的方法继承与队列类,所以常见的方法相同。

  • enQueue(data,priority) 在队尾的位置为队列添加一个新的数据
  • deQueue() 在队头的位置删除队列的第一个元素
  • front() 返回队列的首项
  • isEmpty() 判断队列是否为空
  • size() 返回队列数据的大小
  • toString() 以字符串的形式输出队列中的数据

ES6 实现优先级队列结构

我们可以约定,0 为最高优先级。

  • 优先级数据内部类的实现
class QueueElement {
  constructor(data, priority) {
   // 存放数据
    this.data = data;
    // 存放优先级
    this.priority = priority;
  }
}
  • 优先级队列的实现
/**
 * 优先队列
 *  主要考虑两个问题
 *    1. 队列中的数据不再是单个数据,还要包括优先级
 *    2. 添加元素的过程中根据优先级添加到正确的位置当中
 *
 * @class PriorityQueue
 * @extends {Queue}
 */
class PriorityQueue extends Queue {
  constructor() {
    super();
  }
}
  • enQueue(data, priority) 方法的实现
// 重写 Queue 类 的 enQueue 方法
  enQueue(data, priority) {
    // 创建 优先队列的内部数据类的实例
    const queueData = new QueueElement(data, priority);

    // 判断优先队列是否为空
    if (this.isEmpty()) {
      // 如果优先队列为空 则不需要判断优先级直接添加数据
      this.queue.push(queueData);
    } else {
      // 创建变量 标识该数据是否比现有的优先级小
      let added = false;

      for (let i = 0; i < this.queue.length; i++) {
        // 新插入的数据和现有的数据的优先级做比较,priority 越小 优先级 越大
        if (queueData.priority < this.queue[i].priority) {
          this.queue.splice(i, 0, queueData);
          added = true;
          break;
        }
      }
      if (!added) {
        // 如果遍历完所有元素 没有添加进入队列,则证明优先级小,应该添加到队列的末尾
        this.queue.push(queueData);
      }
    }
  }
  • deQueue() 方法的实现
// dequeue() 出队,从队列中删除前端元素,返回删除的元素
  // 继承 Queue 类的 dequeue()
  deQueue() {
    return super.deQueue();
  }
  • front() 方法的实现
  // front() 查看队列的前端元素
  // 继承 Queue 类的 front()
  front() {
    return super.front();
  }
  • isEmpty() 方法的实现
  // isEmpty() 查看队列是否为空
  // 继承 Queue 类的 isEmpty()
  isEmpty() {
    return super.isEmpty();
  }
  • size() 方法的实现
  // size() 查看队列中元素的个数
  // 继承 Queue 类的 size()
  size() {
    return super.size();
  }
  • toString() 方法的实现
  // toString() 将队列中元素以字符串形式返回
  // 重写 toString()
  toString() {
    let result = "";
    for (let item of this.queue) {
      result += item.data + "-" + item.priority + " ";
    }
    return result;
  }

优先级队列的总体代码

// 优先队列内部的数据类
class QueueElement {
  constructor(data, priority) {
    this.data = data;
    this.priority = priority;
  }
}

/**
 * 优先队列
 *  主要考虑两个问题
 *    1. 队列中的数据不再是单个数据,还要包括优先级
 *    2. 添加元素的过程中根据优先级添加到正确的位置当中
 *
 * @class PriorityQueue
 * @extends {Queue}
 */
class PriorityQueue extends Queue {
  constructor() {
    super();
  }

  // 重写 Queue 类 的 enQueue 方法
  enQueue(data, priority) {
    // 创建 优先队列的内部数据类的实例
    const queueData = new QueueElement(data, priority);

    // 判断优先队列是否为空
    if (this.isEmpty()) {
      // 如果优先队列为空 则不需要判断优先级直接添加数据
      this.queue.push(queueData);
    } else {
      // 创建变量 标识该数据是否比现有的优先级小
      let added = false;

      for (let i = 0; i < this.queue.length; i++) {
        // 新插入的数据和现有的数据的优先级做比较,priority 越小 优先级 越大
        if (queueData.priority < this.queue[i].priority) {
          this.queue.splice(i, 0, queueData);
          added = true;
          break;
        }
      }
      if (!added) {
        // 如果遍历完所有元素 没有添加进入队列,则证明优先级小,应该添加到队列的末尾
        this.queue.push(queueData);
      }
    }
  }

  // dequeue() 出队,从队列中删除前端元素,返回删除的元素
  // 继承 Queue 类的 dequeue()
  deQueue() {
    return super.deQueue();
  }

  // front() 查看队列的前端元素
  // 继承 Queue 类的 front()
  front() {
    return super.front();
  }

  // isEmpty() 查看队列是否为空
  // 继承 Queue 类的 isEmpty()
  isEmpty() {
    return super.isEmpty();
  }

  // size() 查看队列中元素的个数
  // 继承 Queue 类的 size()
  size() {
    return super.size();
  }

  // toString() 将队列中元素以字符串形式返回
  // 重写 toString()
  toString() {
    let result = "";
    for (let item of this.queue) {
      result += item.data + "-" + item.priority + " ";
    }
    return result;
  }
}