JS实现链表数据结构的代码详解

 更新时间:2024年01月22日 08:55:46   作者:翰玥  
很多前端的同学对数据结构和算法这块没有太多的概念,很多leetcode的题目看不懂,有时候可能看了题解也不知道是什么意思,这篇文章咱们来简单的谈一谈链表,文中给大家介绍了JS实现链表数据结构的示例代码,需要的朋友可以参考下

什么是链表

定义:链表是一种递归的数据结构,它或者空(null),或者是指向一个结点(node)的引用,该结点含有一个泛型的元素和一个指向另一条链表的引用。(摘抄自《算法第四版》)不是很好的理解?下面来简单的解释一下。

数组大家肯定都知道。我们想要存储多个元素的时候,数组可能是比较常见的一种数据结构。但是不知道大家有没有考虑过这一点,数组的大小是固定的,如果想要给数组中随意的插入或者移除元素的时候,则需要移动其他的元素,那么成本是很高的。

而链表是有序的元素集合,与数组不同的是,链表中的元素在内存中并不是连续放置的。每个元素由一个存储元素本身的节点和一个指向下一个元素的引用(也称指针或链接)组成。那么链表相对于数组而言它的好处在于,添加或者移除元素的时候,不需要移动其他的元素。

那么再来说说查找,数组中可以通过索引直接访问任何位置的元素,但是链表则需要从起点开始迭代链表直到找到要查找的元素。下面我们用一张图来标示链表:

JS实现一个链表

下面我们用js实现一个链表 大家在刷leetcode链表的题目的时候,是不是都会看到这样的代码

这个其实就是创建链表每个节点的构造函数。这里我们用类来实现

Node类

class Node {
  constructor(val) {
    this.val = val;
    this.next = null;
  }
}

创建链表类

class LinkNodeList {
  constructor() {
    this.head = null;
    this.count = 0;
  }
}

head表示头节点,count表示链表节点个数。 我们需要实现哪些方法呢?

  • push(element):向链表尾部添加一个新元素。
  • insert(element, position):向链表的特定位置插入一个新元素。
  • getVal(index):返回链表中特定位置的元素。如果链表中不存在这样的元素,则返回undefined。
  • remove(position):从链表的特定位置移除一个元素。
  • isEmpty():如果链表中不包含任何元素,返回true,如果链表长度大于0则返回false。
  • size():返回链表包含的元素个数,与数组的length属性类似。
  • toString():返回表示整个链表的字符串。

size

class LinkNodeList {
  constructor() {
    this.head = null;
    this.count = 0;
  }
  ···
  size() {
        return this.count;
  }
  ···
}

用count记录节点个数,直接返回count即可

isEmpty

class LinkNodeList {
  constructor() {
    this.head = null;
    this.count = 0;
  }
  ···
  isEmpty() {
        return this.size() === 0;
  }
  ···
}

直接判断size 是否为0即可

push

向链表尾部添加一个新元素。

class LinkNodeList {
  constructor() {
    this.head = null;
    this.count = 0;
  }
  ···
  push(element) {
    const node = new Node(element);
    
    if (this.head === null) {
        this.head = node;
    } else {
        let current; = this.head;
        while (current.next) {
            current = current.next;
        }
        current.next = node;
    }
    this.count++;
  }
  ···
}

如果想链表的尾部添加一个元素,那么首先需要通过上面实现的Node类来创建一个节点。如果当前的head还不存在,则说明当前的链表还是一个空,所以直接将head节点赋值即可。否则就找到链表的最后一个节点,将它的next指向新push的节点即可。并且将count增加

getVal

返回链表中特定位置的元素

class LinkNodeList {
  constructor() {
    this.head = null;
    this.count = 0;
  }
  ···
  getVal(index) {
    if (index > 0 && index <= this.count) {
        let node = this.head;
        for (let i = 0; i < index; i++) {
                node = node.next;
        }
        return node;
    }
    return undefined;
   }
  ···
}

给getVal传入我们想要查找的位置,首先判断要查找的位置是否存在,如果不存在则直接返回undefined.

存在的话,则从头节点开始循环查找,直到找到目标index。结束循环时,node元素就是index位置元素的引用。

insert(element, position)

向链表的特定位置插入一个新元素。

class LinkNodeList {
  constructor() {
    this.head = null;
    this.count = 0;
  }
  ···
  insert(ele, index) {
    if (index >= 0 && index <= this.count) {
        const node = new Node(ele);
        if (index === 0) {
            const current = this.head;
            node.next = current;
            this.head = node;
        } else {
            const prev = this.getVal(index - 1);
            node.next = prev.next;
            prev.next = node;
        }
        this.count++;
        return true;
    }
    return false;
   }
  ···
}

首先需要判断要插入的位置是否存在,如果不存在则直接返回false,表示不能插入

如果存在,则说明可以插入,那么创建一个节点。如果需要插入的位置为头节点,那么需要将新创建的节点的next指向头节点即可。

如果需要插入的是其他位置,则获取需要插入位置的前一个节点prev,将当前新插入的节点的next,指向prev的下一个节点。然后再将prev的next重新指向需要插入的节点node即可。

只要是有效的插入元素,都需要对count更新

remove(position)

从链表中移除一个元素。

class LinkNodeList {
  constructor() {
    this.head = null;
    this.count = 0;
  }
  ···
  remove(index) {
    if (index >= 0 && index < this.count) {
            let current = this.head;
            // 移除第一项
            if (index === 0) {
                    this.head = current.next;
            } else {
                    const prev = this.getVal(index - 1);
                    current = prev.next;
                    prev.next = current.next;
            }
            this.count--;
            return current.val;
    }

    return undefined;
  }
  ···
}

首先要判断需要移除的值是否存在,如果不存在则返回undefined

如果移除的是第一个节点,则直接将头节点指向下一个节点即可。

如果是其他位置的节点,则首先获取需要移除位置节点的前面一个节点prev,将prev的next,指向下一个,再下一个节点即可

只要是有效的移除元素,都需要对count更新

toString()

返回表示整个链表的字符串。由于列表项使用了Node类,就需要重写继承自JavaScript对象默认的toString方法,让其只输出元素的值。

class LinkNodeList {
  constructor() {
    this.head = null;
    this.count = 0;
  }
  ···
    toString() {
        if (this.head === null) {
            return "";
        }
        let objString = `${this.head.val}`;
        let current = this.head.next;
        for (let i = 1; i < this.size() && current !== null; i++) {
            objString = `${objString}=>${current.val}`;
            current = current.next;
        }
        return objString;
    }
  ···
}

如果头节点不存在,则说明是个空链表则直接返回空

接下来要做的事情就是将链表的每个元素通过“=>”字符串拼接。下面我们看下效果。

以上就是JS实现链表数据结构的代码详解的详细内容,更多关于JS实现链表数据结构的资料请关注脚本之家其它相关文章!

相关文章

  • 详解JavaScript+Canvas绘制环形进度条

    详解JavaScript+Canvas绘制环形进度条

    canvas可以在页面中设定一个区域,再利用JavaScript动态地绘制图像。本文将利用canvas绘制一个可以动的环形进度条。文中的示例代码讲解详细,感兴趣的小伙伴可以动手试一试
    2022-02-02
  • Webpack设置环境变量的一些误区详解

    Webpack设置环境变量的一些误区详解

    这篇文章主要给大家介绍了关于Webpack设置环境变量的一些误区,文中通过示例代码介绍的非常详细,对大家学习或者使用Webpack具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-12-12
  • JavaScript 轮播图和自定义滚动条配合鼠标滚轮分享代码贴

    JavaScript 轮播图和自定义滚动条配合鼠标滚轮分享代码贴

    本文给大家分享一段js轮播图和自定义滚动条的代码片段,布局和样式小编没给大家多介绍,大家可以根据个人需求优化,具体实现代码,大家可以参考下面代码片段
    2016-10-10
  • 前端如何用canvas实现图片的等比例缩放

    前端如何用canvas实现图片的等比例缩放

    这篇文章主要介绍了如何使用HTML和JavaScript加载、读取、缩放和绘制图片到canvas上的相关资料,文中通过代码介绍的非常详细,对大家的学习或者工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2024-11-11
  • Js检查变量类型的代码()

    Js检查变量类型的代码()

    本文章为你提供一款js 返回变量的类型代码哦,如果你不懂得如何获取js变量的类型的话,看看我们下面的代码你就知道如何获取js变量的代码哦。
    2010-07-07
  • 微信小程序实现天气预报功能(附源码)

    微信小程序实现天气预报功能(附源码)

    这篇文章主要介绍了微信小程序实现天气预报功能(附源码),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-12-12
  • javascript 读取内联之外的样式(style、currentStyle、getComputedStyle区别介绍)

    javascript 读取内联之外的样式(style、currentStyle、getComputedStyle区别介绍

    最常用的是style属性,在JavaScript中,通过document.getElementById(id).style.XXX就可以获取到XXX的值,但意外的是,这样做只能取到通过内嵌方式设置的样式值,即style属性里面设置的值。
    2010-05-05
  • JavaScript中的闭包

    JavaScript中的闭包

    闭包,官方对闭包的解释是:一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分
    2016-02-02
  • JavaScript编写一个贪吃蛇游戏

    JavaScript编写一个贪吃蛇游戏

    本文主要介绍了JavaScript写的一个贪吃蛇游戏的实例,具有很好的参考价值。下面跟着小编一起来看下吧
    2017-03-03
  • javascript cookie操作类的实现代码小结附使用方法

    javascript cookie操作类的实现代码小结附使用方法

    javascript cookie操作类的实现代码小结附使用方法,对于cookies操作不是很熟悉的朋友可以参考下。
    2010-06-06

最新评论