学习 TypeScript 栈和队列数据结构

栈和队列都是「操作受限」的数据结构。和基本的数组和链表相比,它们提供的 API 是不完整的。

队列只允许在队尾插入元素,在队头删除元素,栈只允许在栈顶插入元素,从栈顶删除元素。

本篇文章重点介绍栈和队列两种数据结构的 TypeScript 代码实现。

栈代码实现

首先,我们要知道栈数据结构的基本 API 如下:

typescript 复制代码
export class Stack<T> {
  // 栈增操作,从栈顶插入元素
  push(element: T): void {

  }

  // 栈删操作,移除栈顶的元素并返回
  pop(): T | undefined {

  }

  // 删查操作,获取栈顶的元素,但不删除
  peek(): T | undefined {

  }

  // 辅助方法,判断栈是否为空
  isEmpty(): boolean {

  }

  // 辅助方法,返回栈的大小
  size(): number {

  }
}

然后我们要考虑到,在 TypeScript 中,栈可以基于三种数据结构来实现:

  1. 基于数组实现
  2. 基于对象实现
  3. 基于链表实现

下面我们依次来看这三种实现方式。

基于数组代码实现

我们直接看代码吧:

typescript 复制代码
export class Stack<T> {
  // 存储栈元素的数组
  private items: T[] = [];

  constructor() {
    this.items = [];
  }

  // 栈增操作,从栈顶插入元素
  push(element: T): void {
    this.items.push(element);
  }

  // 栈删操作,移除栈顶的元素并返回
  pop(): T | undefined {
    if (this.isEmpty()) {
      return undefined;
    }
    return this.items.pop();
  }

  // 删查操作,获取栈顶的元素,但不删除
  peek(): T | undefined {
    if (this.items.length === 0) {
      return undefined;
    }
    return this.items[this.count - 1];
  }

  // 辅助方法,判断栈是否为空
  isEmpty(): boolean {
    return this.size() === 0;
  }

  // 辅助方法,返回栈的大小
  size(): number {
    return this.items.length;
  }
}

基于对象代码实现

我们直接看代码吧:

typescript 复制代码
export class Stack<T> {
  // 栈的元素数量
  private count: number;
  // 存储栈元素的对象
  private items: Record<number, T> = {};

  // 栈增操作,从栈顶插入元素
  push(element: T): void {
    this.items[this.count] = element;
    this.count++;
  }

  // 栈删操作,移除栈顶的元素并返回
  pop(): T | undefined {
    if (this.isEmpty()) {
      return undefined;
    }
    const element = this.items[this.count - 1];
    delete this.items[this.count - 1];
    this.count--;
    return element;
  }

  // 删查操作,获取栈顶的元素,但不删除
  peek(): T | undefined {
    if (this.isEmpty()) {
      return undefined;
    }
    return this.items[this.count - 1];
  }

  // 辅助方法,判断栈是否为空
  isEmpty(): boolean {
    return this.size() === 0;
  }

  // 辅助方法,返回栈的大小
  size(): number {
    return this.count;
  }
}

基于链表代码实现

我们考虑用双向链表来实现栈,看下面的代码:

typescript 复制代码
export class Stack<T> {
  // 存储栈元素的双向链表
  private items: DoublyLinkedList<T>;

  constructor() {
    this.items = new DoublyLinkedList();
  }

  // 栈增操作,从栈顶插入元素
  push(element: T): void {
    this.items.push(element);
  }

  // 栈删操作,移除栈顶的元素并返回
  pop(): T | undefined {
    if (this.items.isEmpty()) {
      return undefined;
    }
    return this.items.pop();
  }

  // 删查操作,获取栈顶的元素,但不删除
  peek(): T | undefined {
    if (this.items.isEmpty()) {
      return undefined;
    }
    return this.items.getTail().element;
  }

  // 辅助方法,判断栈是否为空
  isEmpty(): boolean {
    return this.items.isEmpty();
  }

  // 辅助方法,返回栈的大小
  size(): number {
    return this.items.size();
  }
}

队列

首先,我们要知道队列数据结构的基本 API 如下:

typescript 复制代码
export class Queue<T> {
  // 队列增操作,在队尾添加一个元素
  enquque(element: T): void {

  }

  // 队列删操作,移除队头的元素并返回
  dequeue(): T | undefined {

  }

  // 队列查操作,查看队头元素
  peek(): T | undefined {

  }

  // 辅助方法,判断队列是否为空
  isEmpty(): boolean {

  }

  // 辅助方法,返回队列的长度
  size(): number {

  }
}

然后我们要考虑到,在 TypeScript 中,队列可以基于三种数据结构来实现:

  1. 基于数组实现
  2. 基于对象实现
  3. 基于链表实现

下面我们依次来看这三种实现方式。

基于数组代码实现

我们直接看代码吧:

typescript 复制代码
export class Queue<T> {
  // 存储队列元素的数组
  private items: T[];

  constructor() {
    this.items = [];
  }

  // 队列增操作,在队尾添加一个元素
  enquque(element: T): void {
    this.items.push(element);
  }

  // 队列删操作,移除队头的元素并返回
  dequeue(): T | undefined {
    if (this.isEmpty()) {
      return undefined;
    }
    return this.items.pop();
  }

  // 队列查操作,查看队头元素
  peek(): T | undefined {
    if (this.isEmpty()) {
      return undefined;
    }
    return this.items[this.size() - 1];
  }

  // 辅助方法,判断队列是否为空
  isEmpty(): boolean {
    return this.size() === 0;
  }

  // 辅助方法,返回队列的长度
  size(): number {
    return this.items.length;
  }
}

基于对象代码实现

我们直接看代码吧:

typescript 复制代码
export class Queue<T> {
  private count: number;
  private lowestCount: number;
  private items: Record<number, T>;

  contructor() {
    this.count = 0;
    this.lowestCount = 0;
    this.items = {};
  }

  // 队列增操作,在队尾添加一个元素
  enquque(element: T): void {
    this.items[this.count] = element;
    this.count++;
  }

  // 队列删操作,移除队头的元素并返回
  dequeue(): T | undefined {
    if (this.isEmpty()) {
      return undefined;
    }
    const element = this.items[this.lowestCount];
    delete this.items[this.lowestCount];
    this.lowestCount++;
    return element;
  }

  // 队列查操作,查看队头元素
  peek(): T | undefined {
    if (this.isEmpty()) {
      return undefined;
    }
    return this.items[this.lowestCount];
  }

  // 辅助方法,判断队列是否为空
  isEmpty(): boolean {
    return this.size() === 0;
  }

  // 辅助方法,返回队列的长度
  size(): number {
    return this.count - this.lowestCount;
  }
}

基于链表代码实现

我们考虑用双向链表来实现栈,看下面的代码:

typescript 复制代码
export class Queue<T> {
  private items: DoublyLinkedList<T>;

  constructor() {
    this.items = new DoublyLinkedList();
  }

  // 队列增操作,在队尾添加一个元素
  enquque(element: T): void {
    this.items.push(element);
  }

  // 队列删操作,移除队头的元素并返回
  dequeue(): T | undefined {
    if (this.items.isEmpty()) {
      return undefined;
    }
    const element = this.items.getHead().element;
    this.items.shift();
    return element;
  }

  // 队列查操作,查看队头元素
  peek(): T | undefined {
    if (this.items.isEmpty()) {
      return undefined;
    }
    return this.items.getHead().element;
  }

  // 辅助方法,判断队列是否为空
  isEmpty(): boolean {
    return this.items.isEmpty();
  }

  // 辅助方法,返回队列的长度
  size(): number {
    return this.items.size();
  }
}

双端队列

标准队列只能在队尾插入元素,队头删除元素,而双端队列的队头和队尾都可以插入或删除元素。

我们要知道双端队列数据结构的基本 API 如下:

typescript 复制代码
export class Deque<T> {
  // 双端队列增操作,在队尾添加一个元素
  addLast(element: T): void {

  }

  // 双端队列增操作,在队头添加一个元素
  addFirst(element: T): void {

  }

  // 双端队列删操作,移除队尾的元素并返回
  removeLast(): T | undefined {

  }

  // 双端队列删操作,移除队头的元素并返回
  removeFirst(): T | undefined {

  }

  // 双端队列查操作,查看队尾的元素
  peekLast(): T | undefined {

  }

  // 双端队列查操作,查看队头的元素
  peekFirst(): T | undefined {

  }

  // 辅助方法,判断双端队列是否为空
  isEmpty(): boolean {

  }

  // 辅助方法,返回双端队列的长度。
  size(): number {

  }
}

基于数组代码实现

我们直接看代码吧:

typescript 复制代码
export class Deque<T> {
  // 存储队列元素的数组
  private items: T[];

  constructor() {
    this.items = [];
  }

  // 双端队列增操作,在队尾添加一个元素
  addLast(element: T): void {
    this.items.push(element);
  }

  // 双端队列增操作,在队头添加一个元素
  addFirst(element: T): void {
    this.items.unshift(element);
  }

  // 双端队列删操作,移除队尾的元素并返回
  removeLast(): T | undefined {
    if (this.isEmpty()) {
      return undefined;
    }
    return this.items.pop();
  }

  // 双端队列删操作,移除队头的元素并返回
  removeFirst(): T | undefined {
    if (this.isEmpty()) {
      return undefined;
    }
    return this.items.shift();
  }

  // 双端队列查操作,查看队尾的元素
  peekLast(): T | undefined {
    if (this.isEmpty()) {
      return undefined;
    }
    return this.items[this.size() - 1];
  }

  // 双端队列查操作,查看队头的元素
  peekFirst(): T | undefined {
    if (this.isEmpty()) {
      return undefined;
    }
    return this.items[0];
  }

  // 辅助方法,判断双端队列是否为空
  isEmpty(): boolean {
    return this.size() === 0;
  }

  // 辅助方法,返回双端队列的长度。
  size(): number {
    return this.items.length;
  }
}

基于对象代码实现

我们直接看代码吧:

typescript 复制代码
export class Deque<T> {
  private count: number;
  private lowestCount: number;
  private items: Record<number, T>;

  constructor() {
    this.count = 0;
    this.lowestCount = 0'
    this.items = {};
  }

  // 双端队列增操作,在队尾添加一个元素
  addLast(element: T): void {
    this.items[this.count] = element;
    this.count++;
  }

  // 双端队列增操作,在队头添加一个元素
  addFirst(element: T): void {
    if (this.lowestCount > 0) {
      this.items[this.lowestCount] = element;
      this.lowestCount--;
    } else {
      for (let i = this.count; i > this.lowestCount; i--) {
        this.items[i] = this.items[i - 1];
      }
      this.items[this.lowestCount] = element;
      this.count++;
    }
  }

  // 双端队列删操作,移除队尾的元素并返回
  removeLast(): T | undefined {
    if (this.isEmpty()) {
      return undefined;
    }
    const element = this.items[this.count - 1];
    delete this.items[this.count - 1];
    this.count--;
    return element;
  }

  // 双端队列删操作,移除队头的元素并返回
  removeFirst(): T | undefined {
    if (this.isEmpty()) {
      return undefined;
    }
    const element = this.items[this.lowestCount];
    delete this.items[this.lowestCount];
    this.lowestCount++;
    return element;
  }

  // 双端队列查操作,查看队尾的元素
  peekLast(): T | undefined {
    if (this.isEmpty()) {
      return undefined;
    }
    return this.items[this.count - 1];
  }

  // 双端队列查操作,查看队头的元素
  peekFirst(): T | undefined {
    if (this.isEmpty()) {
      return undefined;
    }
    return this.items[this.lowestCount];
  }

  // 辅助方法,判断双端队列是否为空
  isEmpty(): boolean {
    return this.size() === 0;
  }

  // 辅助方法,返回双端队列的长度。
  size(): number {
    return this.count - this.lowestCount;
  }
}

基于链表代码实现

我们考虑用双向链表来实现栈,看下面的代码:

typescript 复制代码
export class Deque<T> {
  private items: DoublyLinkedList<T>;

  // 双端队列增操作,在队尾添加一个元素
  addLast(element: T): void {
    this.items.push(element);
  }

  // 双端队列增操作,在队头添加一个元素
  addFirst(element: T): void {
    this.items.unshift(element);
  }

  // 双端队列删操作,移除队尾的元素并返回
  removeLast(): T | undefined {
    if (this.isEmpty()) {
      return undefined;
    }
    return this.items.pop();
  }

  // 双端队列删操作,移除队头的元素并返回
  removeFirst(): T | undefined {
    if (this.isEmpty()) {
      return undefined;
    }
    return this.items.shift();
  }

  // 双端队列查操作,查看队尾的元素
  peekLast(): T | undefined {
    if (this.isEmpty()) {
      return undefined;
    }
    return this.items.getTail().element;
  }

  // 双端队列查操作,查看队头的元素
  peekFirst(): T | undefined {
    if (this.isEmpty()) {
      return undefined;
    }
    return this.items.getHead().element;
  }

  // 辅助方法,判断双端队列是否为空
  isEmpty(): boolean {
    return this.items.isEmpty();
  }

  // 辅助方法,返回双端队列的长度。
  size(): number {
    return this.items.size();
  }
}
相关推荐
yaoh.wang1 天前
力扣(LeetCode) 13: 罗马数字转整数 - 解法思路
python·程序人生·算法·leetcode·面试·职场和发展·跳槽
AI浩1 天前
【Labelme数据操作】LabelMe标注批量复制工具 - 完整教程
运维·服务器·前端
涔溪1 天前
CSS 网格布局(Grid Layout)核心概念、基础语法、常用属性、实战示例和进阶技巧全面讲解
前端·css
T1ssy1 天前
布隆过滤器:用概率换空间的奇妙数据结构
算法·哈希算法
2401_878454531 天前
浏览器工作原理
前端·javascript
西陵1 天前
为什么说 AI 赋能前端开发,已经不是选择题,而是必然趋势?
前端·架构·ai编程
hetao17338371 天前
2025-12-12~14 hetao1733837的刷题笔记
数据结构·c++·笔记·算法
鲨莎分不晴1 天前
强化学习第五课 —— A2C & A3C:并行化是如何杀死经验回放
网络·算法·机器学习
by__csdn1 天前
Vue3 setup()函数终极攻略:从入门到精通
开发语言·前端·javascript·vue.js·性能优化·typescript·ecmascript
天天扭码1 天前
前端如何实现RAG?一文带你速通,使用RAG实现长期记忆
前端·node.js·ai编程