基于链表结构实现队列

简介: 在之前的文章《如何实现一个队列》中,我们使用数组结构、栈结构实现了队列,现在我们要寻找一种更优雅的方案来实现队列。

前言


在之前的文章《如何实现一个队列》中,我们使用数组结构、栈结构实现了队列,现在我们要寻找一种更优雅的方案来实现队列。


链表是一种有序的,零散的数据存储结构,区分为单项链表和双向链表。


  • 单项链表:链表节点会存储一个下一个节点对象的引用地址,如next属性;


  • 双向链表:链表节点会同时存储指向上一个节点对象的引用(prev)和下一个节点对象的引用(next)。


我们先来回忆下队列的特点:有序,队列元素遵循先进先出,后进后出的原则。


队列实现 - 链表


首先声明一个链表类,具备以下方法和属性。


属性或方法 描述
add() 添加队列元素的方法
delete() 删除队列元素的方法
length 获取队列元素长度的属性


创建链表类


// 定义链表节点类型
interface LinkedListNode {
  value: number;
  next: LinkedListNode | null;
}
// 链表类
class LinkedList {
  // 私有属性,表示队头节点
  private head: LinkedListNode | null = null;
  // 私有属性,表示队尾节点
  private tail: LinkedListNode | null = null;
  // 私有属性,用来表示队列的长度
  private len: number = 0;
  /**
   * @method add
   * @description 添加队列元素,添加到队头位置
   * @param n number
   */
  add(n: number) {
    // 生成链表节点
    const node: LinkedListNode = {
      value: n,
      next: null,
    };
    // head节点特殊处理
    if (this.head === null) {
      this.head = node;
    }
    // 获取当前tail节点
    const tailNode = this.tail;
    // 当前tail节点存在,则将next指针,指向node
    if (tailNode) {
      tailNode.next = node;
    }
    // 更新tail节点的指向
    this.tail = node;
    // 注意,这里队列长度单独计算的,长度+1
    this.len++;
  }
  /**
   * @method delete
   * @description 出队 - 从队头出
   * @returns number | null
   */
  delete(): number | null {
    // 获取head节点
    const headNode = this.head;
    // 特殊情况处理
    if (headNode === null) return null;
    // 有了长度的为0的判断,就不用处理tail节点的指向了
    if (this.len === 0) return null;
    // 获取头结点的值
    const value = headNode.value;
    // 更新头结点的指向
    this.head = headNode.next;
    // 队列长度 -1
    this.len--;
    // 返回结果
    return value;
  }
  /**
   * @description 返回队列的长度
   */
  get length(): number {
    return this.len;
  }
}


性能测试


// 入队10W个元素
console.time('add - linkedList');
for (let i = 0; i < 10 * 10000; i++) {
  linkedListQueue.add(i);
}
console.log(linkedListQueue.length);
console.timeEnd('add - linkedList');
console.time('delete - linkedList');
for (let i = 0; i < 10000; i++) {
  linkedListQueue.delete();
}
console.timeEnd('delete - linkedList');


网络异常,图片无法展示
|


算法复杂度分析下:


  1. 空间复杂度就是O(n)O(n)O(n),随着n的增大,链表空间长度线性增长;


  1. 时间复杂度 add方法 O(1)O(1)O(1)、delete方法O(1)O(1)O(1),还是非常OK的。


可对比下上一篇文章《如何实现一个队列》中实现队列的两种方式的性能。


所以,性能对比下,使用链表实现队列的形式是最优的!


相关文章
|
7月前
|
Python
Python实现数据结构(如:链表、栈、队列等)。
Python实现数据结构(如:链表、栈、队列等)。
280 0
|
2月前
|
存储 算法 搜索推荐
探索常见数据结构:数组、链表、栈、队列、树和图
探索常见数据结构:数组、链表、栈、队列、树和图
112 64
|
4月前
【刷题记录】链表的回文结构
【刷题记录】链表的回文结构
|
4月前
|
存储 Java 开发者
揭秘!HashMap底层结构大起底:从数组到链表,再到红黑树,Java性能优化的秘密武器!
【8月更文挑战第24天】HashMap是Java集合框架中的核心组件,以其高效的键值对存储和快速访问能力广受开发者欢迎。在JDK 1.8及以后版本中,HashMap采用了数组+链表+红黑树的混合结构,实现了高性能的同时解决了哈希冲突问题。数组作为基石确保了快速定位;链表则用于处理哈希冲突;而当链表长度达到一定阈值时,通过转换为红黑树进一步提升性能。此外,HashMap还具备动态扩容机制,当负载因子超过预设值时自动扩大容量并重新哈希,确保整体性能。通过对HashMap底层结构的深入了解,我们可以更好地利用其优势解决实际开发中的问题。
117 0
|
5月前
【数据结构OJ题】链表的回文结构
牛客题目——链表的回文结构
43 0
【数据结构OJ题】链表的回文结构
|
6月前
|
数据安全/隐私保护
第2章 栈、队列、链表
第2章 栈、队列、链表
|
6月前
|
存储 算法
数据结构和算法学习记录——二叉树的存储结构&二叉树的递归遍历(顺序存储结构、链表存储结构、先序中序后序递归遍历)
数据结构和算法学习记录——二叉树的存储结构&二叉树的递归遍历(顺序存储结构、链表存储结构、先序中序后序递归遍历)
72 0
数据结构和算法学习记录——二叉树的存储结构&二叉树的递归遍历(顺序存储结构、链表存储结构、先序中序后序递归遍历)
|
6月前
|
算法 C语言
【数据结构与算法 经典例题】链表的回文结构(图文详解)
【数据结构与算法 经典例题】链表的回文结构(图文详解)
|
6月前
|
存储
【数据结构】详解链表结构
【数据结构】详解链表结构
28 0
|
7月前
|
算法 测试技术
【数据结构与算法 | 基础篇】单向循环链表实现队列
【数据结构与算法 | 基础篇】单向循环链表实现队列