返回

队列与双端队列:TypeScript实现,从基础到应用

前端

前言

队列是一种先进先出的数据结构,元素按照进入队列的顺序依次排列,先进入队列的元素先被处理。双端队列是一种特殊的队列,它允许从队首和队尾添加或删除元素。

队列和双端队列在计算机科学中有很多应用,例如:

  • 进程调度:操作系统使用队列来调度进程,先进入队列的进程先被执行。
  • 消息传递:消息队列用于在进程之间传递消息。
  • 数据缓冲:队列用于缓冲数据,以便在需要时使用。

TypeScript实现

队列

class Queue<T> {
  private items: T[] = [];

  enqueue(item: T): void {
    this.items.push(item);
  }

  dequeue(): T | undefined {
    return this.items.shift();
  }

  peek(): T | undefined {
    return this.items[0];
  }

  isEmpty(): boolean {
    return this.items.length === 0;
  }
}

双端队列

class Deque<T> {
  private items: T[] = [];

  enqueueFront(item: T): void {
    this.items.unshift(item);
  }

  enqueueBack(item: T): void {
    this.items.push(item);
  }

  dequeueFront(): T | undefined {
    return this.items.shift();
  }

  dequeueBack(): T | undefined {
    return this.items.pop();
  }

  peekFront(): T | undefined {
    return this.items[0];
  }

  peekBack(): T | undefined {
    return this.items[this.items.length - 1];
  }

  isEmpty(): boolean {
    return this.items.length === 0;
  }
}

应用

经典问题一:约瑟夫环

约瑟夫环问题是一个经典的计算机科学问题。问题是这样的:有n个人围成一圈,从第一个人开始,依次报数,数到m的人出列,然后从下一个人开始继续报数,直到只剩下一个人。求最后剩下的那个人。

我们可以用队列来解决这个问题。首先,我们将n个人加入队列。然后,从队首开始报数,数到m的人出列。然后,我们将队首的人移动到队尾,继续报数。重复这个过程,直到只剩下一个人。

function josephus(n: number, m: number): number {
  const queue = new Queue<number>();
  for (let i = 1; i <= n; i++) {
    queue.enqueue(i);
  }

  while (queue.size() > 1) {
    for (let i = 0; i < m - 1; i++) {
      queue.enqueue(queue.dequeue());
    }
    queue.dequeue();
  }

  return queue.dequeue();
}

经典问题二:迷宫问题

迷宫问题是一个经典的计算机科学问题。问题是这样的:给定一个迷宫,求从起点到终点的最短路径。

我们可以用双端队列来解决这个问题。首先,我们将起点加入双端队列。然后,我们将双端队列队首的元素出列,并将其相邻的未访问过的元素加入双端队列。重复这个过程,直到双端队列队尾的元素是终点。

function maze(maze: number[][], start: number[], end: number[]): number[][] {
  const queue = new Deque<number[]>();
  queue.enqueueFront(start);

  while (!queue.isEmpty()) {
    const current = queue.dequeueFront();
    if (current[0] === end[0] && current[1] === end[1]) {
      return queue;
    }

    const neighbors = getNeighbors(current, maze);
    for (const neighbor of neighbors) {
      if (!visited(neighbor, queue)) {
        queue.enqueueBack(neighbor);
      }
    }
  }

  return [];
}

function getNeighbors(current: number[], maze: number[][]): number[][] {
  const neighbors: number[][] = [];
  if (current[0] > 0 && maze[current[0] - 1][current[1]] === 0) {
    neighbors.push([current[0] - 1, current[1]]);
  }
  if (current[0] < maze.length - 1 && maze[current[0] + 1][current[1]] === 0) {
    neighbors.push([current[0] + 1, current[1]]);
  }
  if (current[1] > 0 && maze[current[0]][current[1] - 1] === 0) {
    neighbors.push([current[0], current[1] - 1]);
  }
  if (current[1] < maze[0].length - 1 && maze[current[0]][current[1] + 1] === 0) {
    neighbors.push([current[0], current[1] + 1]);
  }

  return neighbors;
}

function visited(current: number[], queue: Deque<number[]>): boolean {
  for (const item of queue.items) {
    if (item[0] === current[0] && item[1] === current[1]) {
      return true;
    }
  }

  return false;
}

总结

队列和双端队列是计算机科学中常用的数据结构。本文用TypeScript实现了队列和双端队列,并用其解决了计算机科学领域中的两道经典问题。通过本文,您对队列和双端队列有了更深入的了解,并学习了如何用TypeScript实现它们。