JavaScript数据结构链表知识详解

JavaScript数据结构链表知识详解

什么是链表

链表是一种线性结构,相比于数组,它不需要一块连续的内存空间,而是通过指针将一组零散的内存块串联起来使用。链表只保持一个指向链表中第一个节点的引用,每个节点则有指向下一个节点的指针。

链表的实现

链表的实现方式有很多种,下面介绍一种简单的单向链表实现方式,其中每个节点包含一个value属性和一个next属性,next属性指向下一个节点(没有则为null)。

class ListNode {
  constructor(value) {
    this.value = value;
    this.next = null;
  }
}

class LinkedList {
  constructor() {
    this.head = null;
    this.length = 0;
  }

  append(value) {
    const node = new ListNode(value);
    if (this.head === null) {
      // 链表为空,添加第一个节点
      this.head = node;
    } else {
      // 链表不为空,遍历到最后一个节点,添加新的节点
      let current = this.head;
      while (current.next !== null) {
        current = current.next;
      }
      current.next = node;
    }
    this.length++;
  }

  insert(value, position) {
    if (position < 0 || position > this.length) {
      // 如果指定的位置小于0或大于链表长度,不能插入
      return false;
    }
    const node = new ListNode(value);
    if (position === 0) {
      // 添加到链表头部
      node.next = this.head;
      this.head = node;
    } else {
      // 找到要插入位置的前一个节点,插入节点
      let index = 0;
      let current = this.head;
      let previous = null;
      while (index < position) {
        previous = current;
        current = current.next;
        index++;
      }
      node.next = current;
      previous.next = node;
    }
    this.length++;
    return true;
  }

  remove(position) {
    if (position < 0 || position >= this.length) {
      // 如果指定的位置小于0或大于等于链表长度,不能删除
      return false;
    }
    if (position === 0) {
      // 删除链表头部节点
      this.head = this.head.next;
    } else {
      // 找到要删除位置的前一个节点,删除节点
      let index = 0;
      let current = this.head;
      let previous = null;
      while (index < position) {
        previous = current;
        current = current.next;
        index++;
      }
      previous.next = current.next;
    }
    this.length--;
    return true;
  }

  indexOf(value) {
    let index = 0;
    let current = this.head;
    while (current !== null) {
      if (value === current.value) {
        return index;
      }
      current = current.next;
      index++;
    }
    return -1;
  }

  toString() {
    let listString = '';
    let current = this.head;
    while (current !== null) {
      listString += current.value + ' ';
      current = current.next;
    }
    return listString;
  }
}

链表的应用

链表可以用来解决很多问题,比如:

  1. 链表可以用来实现栈和队列:栈和队列都是顺序访问的数据结构,用数组实现时需要考虑数组的大小问题,而用链表实现则没有这个问题。
  2. 链表可以用来实现哈希表:哈希表需要快速插入、删除和查找元素,使用链表可以实现这个目标。
  3. 链表可以用来实现LRU缓存算法:LRU缓存算法需要快速插入、删除和查找元素,使用链表实现可以达到O(1)的时间复杂度。

下面举两个链表的应用示例:

示例1:用链表实现栈

栈是一种后进先出(LIFO)的数据结构,可以用链表来实现。栈的基本操作包括push、pop和peek。

class Stack {
  constructor() {
    this.list = new LinkedList();
  }

  push(value) {
    this.list.append(value);
  }

  pop() {
    if (this.list.length === 0) {
      return null;
    }
    const index = this.list.length - 1;
    const value = this.list.get(index);
    this.list.remove(index);
    return value;
  }

  peek() {
    if (this.list.length === 0) {
      return null;
    }
    const index = this.list.length - 1;
    return this.list.get(index);
  }

  toString() {
    return this.list.toString();
  }
}

示例2:用链表实现LRU缓存算法

LRU缓存算法(Least Recently Used)是一种常用的缓存淘汰算法,它基于这样一个假设:如果数据最近被访问过,那么将来被访问的几率也很高。根据这个原理,LRU缓存算法将最近最少使用(Least Recently Used)的数据淘汰掉。

class LRUCache {
  constructor(capacity) {
    this.capacity = capacity;
    this.list = new LinkedList();
    this.map = new Map();
  }

  get(key) {
    if (!this.map.has(key)) {
      return null;
    }
    const node = this.map.get(key);
    // 移动到链表头部
    this.list.removeNode(node);
    this.list.addNodeToFront(node);
    return node.value.value;
  }

  put(key, value) {
    if (this.map.has(key)) {
      // 如果已存在,更新值,并移动到链表头部
      const node = this.map.get(key);
      node.value.value = value;
      this.list.removeNode(node);
      this.list.addNodeToFront(node);
    } else {
      // 如果不存在,添加到链表头部
      const node = new ListNode({ key, value });
      this.list.addNodeToFront(node);
      this.map.set(key, node);
      // 检查容量是否超出限制
      if (this.map.size > this.capacity) {
        // 如果超出限制,删除链表尾部节点和map中的对应项
        const nodeToDelete = this.list.tail;
        this.list.removeNode(nodeToDelete);
        this.map.delete(nodeToDelete.value.key);
      }
    }
  }

  toString() {
    return this.list.toString();
  }
}

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:JavaScript数据结构链表知识详解 - Python技术站

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • C语言数据结构之算法的时间复杂度

    关于C语言数据结构之算法的时间复杂度,需要先了解一些基本概念。 什么是时间复杂度 时间复杂度是算法的一种衡量标准,用于评估算法的执行效率。表示代码执行的时间和数据量之间的关系,通常用大O符号来表示,称为“大O记法”。 时间复杂度的分类 时间复杂度可分为以下几类: 常数阶:O(1) 对数阶:O(log n) 线性阶:O(n) 线性对数阶:O(n log n) …

    数据结构 2023年5月17日
    00
  • C语言中关于树和二叉树的相关概念

    C语言中关于树和二叉树的相关概念 树的概念 在计算机科学中,树是一种非常常见的数据结构,它由一组节点(通常称为元素)和一组连接节点的边组成。树是一种无向的、连通的、无环的图形结构,其中有一个节点被称为根节点,它没有父节点,而其他节点都有一个父节点。 树的定义很抽象,但在程序设计中,我们通常会使用一个节点类来实现树结构。一个节点类通常包含两个元素:一个是表示当…

    数据结构 2023年5月17日
    00
  • 浅谈Java数据结构之稀疏数组知识总结

    浅谈Java数据结构之稀疏数组知识总结 稀疏数组的定义 稀疏数组是指当一个数组中大部分元素是相同的值时,可以使用稀疏数组来保存该数组。稀疏数组的必要性在于节省内存空间,当数组中元素过多时,存储数组所需的内存空间也呈指数级增长。 稀疏数组的特点 稀疏数组存储的是一个原始的二维数组。 稀疏数组的第一行保存原始数组的基本信息,包括行数、列数、有效值的个数。 稀疏数…

    数据结构 2023年5月17日
    00
  • 【ACM数论】和式变换技术,也许是最好的讲解之一

    在做数论题时,往往需要进行和式变换,然后变换成我们可以处理的和式,再针对和式做筛法、整除分块等操作。 本文将介绍一些常见的和式变换技术。 以下出现的概念大部分为个人总结,未必是学术界/竞赛界的统一说法,有不严谨的地方请谅解。 ? 作者:Eriktse? 简介:19岁,211计算机在读,现役ACM银牌选手?力争以通俗易懂的方式讲解算法!❤️欢迎关注我,一起交流…

    算法与数据结构 2023年4月17日
    00
  • 深入PHP中的HashTable结构详解

    深入PHP中的HashTable结构详解 在PHP中,HashTable是一种基础数据结构,常用于存储对象的属性和方法等各种数据,本篇攻略将深入介绍HashTable的实现原理和应用。 HashTable的实现原理 HashTable并不是一种单一的数据结构,它可以根据不同的需求来采用不同的实现方式。在PHP中,我们经常使用的是基于链表的实现方式,也就是链式…

    数据结构 2023年5月17日
    00
  • 设要采用CRC编码传送的数据信息x=1001,当生成多项式为G(x)=1101时,请写出它的循环校验码。若接收方收到的数据信息x’ =1101,说明如何定位错误并纠正错误

    题目:设要采用CRC编码传送的数据信息x=1001,当生成多项式为G(x)=1101时,请写出它的循环校验码。若接收方收到的数据信息x’ =1101,说明如何定位错误并纠正错误 根据题目描述,需要采用CRC编码对数据信息x=1001进行编码,生成多项式为G(x)=1101。下面是计算循环冗余校验码的步骤:1.首先将数据信息x乘以x的次数,使得它的位数与G(x…

    算法与数据结构 2023年4月18日
    00
  • C++数据结构之实现邻接表

    C++数据结构之实现邻接表 在图论中,为了表示节点及其之间的联系,我们需要使用数据结构。邻接表是图的一种常见表示方法,实现方便且高效。 什么是邻接表 邻接表是一种图形式的数据结构,由节点和边组成。它使用链式结构来存储相邻节点的信息。邻接表常用于表示有向图、无向图以及加权图。在邻接表中,每一个节点都存储了一个链表,其中包含了该节点与其他节点之间的连接情况。 实…

    数据结构 2023年5月17日
    00
  • Java数据结构常见几大排序梳理

    Java数据结构常见几大排序梳理 在Java中,数据排序是非常常见的操作。下面我们详细讲解一下Java数据结构常见几大排序的梳理。 常见几大排序 Java数据结构中常见几种排序算法包括: 冒泡排序(Bubble Sort) 快速排序(Quick Sort) 插入排序(Insertion Sort) 选择排序(Selection Sort) 希尔排序(Shel…

    数据结构 2023年5月17日
    00
合作推广
合作推广
分享本页
返回顶部