利用JS实现队列

93 阅读3分钟

队列

队列是一种操作受限制的线性表,它只允许在队首进行删除操作,而在队尾进行插入操作。

队列是一种先进先出的数据结构。

队列的实现

根据队列的特性,我们可以看出队首总是在做删除操作,队尾总是在做添加操作。我们可以使用数组和链表模拟队列。数组在头部插入或删除元素会导致后面的所有元素的位置后移或前移,性能不太好。所以建议使用链表实现。

为了避免使用 单向链表 的尾部做删除操作(单向链表尾部删除,新的队尾需要从头查询),应该选择链表的 头元素 作为 队首(仅删除),尾元素 作为 队尾(仅插入)。

class Queue {
  constructor() {
    this.queueList = new LinkedList();
  }
  // 向队列尾部添加新的项
  push(element) {
    this.queueList.append(element);
  }
  // 移除队首元素,并返回被移除的元素
  pop() {
    return this.queueList.removeAt(0);
  }
  // 查看队首元素
  peek() {
    return this.queueList.get(0);
  }
  // 是否为空队列
  isEmpty() {
    return this.queueList.isEmpty();
  }
  // 返回队列包含的元素个数
  size() {
    return this.queueList.size();
  }
  toString() {
    return this.queueList.toString();
  }
}

双向队列

双向队列的概念就是同时允许在队首和队尾添加和删除元素。可先进先出,或后进先出。

双向队列实现

使用 双向链表 模拟双向队列。

class Queue {
  constructor() {
    this.queueList = new LinkedList();
  }
  // 在队列前端添加新的元素
  frontPush(element) {
    this.queueList.insert(0, element);
  }
  // 在队列后端添加新的元素
  backPush(element) {
    this.queueList.append(element);
  }
  // 删除队列前端的第一个元素
  frontPop() {
    return this.queueList.removeAt(0);
  }
  // 删除队列后端的第一个元素
  backPop() {
    return this.queueList.removeAt(this.size() - 1);
  }
  // 返回队列前端的第一个元素
  peekFront() {
    return this.queueList.get(0);
  }
  // 返回队列后端的第一个元素
  peekBack() {
    return this.queueList.get(this.size() - 1);
  }
  // 是否为空队列
  isEmpty() {
    return this.queueList.isEmpty();
  }
  // 返回队列包含的元素个数
  size() {
    return this.queueList.size();
  }
  toString() {
    return this.queueList.toString();
  }
}

输入限制的双向队列

限制一端只能进行删除操作,而另一端不做限制,也就是说插入(输入)操作受到了限制。

输出限制的双向队列

限制一端只能进行插入操作,而另一端不做限制,也就是说删除(输出)操作受到了限制。

优先队列

在队列中,元素被赋予优先级。具有最高优先级的元素最先删除。

优先队列实现

使用 单向链表 模拟优先队列。

class Queue {
  constructor() {
    this.priorityQueue = new LinkedList();
  }
  // 向队列尾部添加新的项
  push(element, priority = 0) {
    let len = this.priorityQueue.size();
    if (len === 0) {
      this.priorityQueue.append({
        element,
        priority
      });
      return;
    }
    for (let index = 0; index < len; index++) {
      const queueItem = this.priorityQueue.get(index);
      // 只有比当前位置的权限高才能插入当前位置
      if (queueItem.priority < priority) {
        this.priorityQueue.insert(index, {
          element,
          priority
        });
        return;
      } else if (index === len - 1) {
        // 不比当前位置的权限高且是最后一个节点,就放到队列最后面
        this.priorityQueue.append({
          element,
          priority
        });
      }
    }
  }
  // 移除队首元素,并返回被移除的元素
  pop() {
    let queueHead = this.priorityQueue.removeAt(0);
    return queueHead && queueHead.element;
  }
  // 查看队首元素
  peek() {
    let queueHead = this.priorityQueue.get(0);
    return queueHead && queueHead.element;
  }
  // 是否为空队列
  isEmpty() {
    return this.priorityQueue.isEmpty();
  }
  // 返回队列包含的元素个数
  size() {
    return this.priorityQueue.size();
  }
  toString() {
    if (this.isEmpty()) {
      return "";
    }
    let temp = [];
    let current = this.priorityQueue.getHead();
    temp.push(current.data.element);
    while (current.next) {
      current = current.next;
      temp.push(current.data.element);
    }
    return temp.toString();
  }
}