js数据结构之-链表

166 阅读4分钟

前端一般工作中很少会用到链表,一般数组对象这种就能满足大部分场景了,我在工作中也没用过链表这种结构。不过在leetcode刷题中,老能见到这种数据结构,所以准备好好研究一下。

什么是数组

如果你简历说你熟悉链表,面试官一般都会简单问一下,数组链表的区别。

在其它编程语言中,数组是一种在内存中用一组连续的内存空间来存储一组具有相同类型的数据。注意连续这俩字。

因为数组这种结构在内存中是连续的,所有CPU执行程序时,去内存中读取数据会一次读取一块(块的大小我也不确定),读取后会保存到CPU的缓存中,下次需要访问内存数据的时候就会先从CPU缓存中找,这和我们平时说的缓存原理一样。

我们都知道内存的读取速度要比硬盘快的多,同样CPU缓存要比内存快的多,因为数组在内存中连续的原因,可以让CPU很好的缓存,所以结论来了。

数组可以通过下标实现O1复杂度的随机访问,说人话就是,数组访问一个元素非常快

但是,但是,js中数组是用对象来实现的,所以下面方法无法准确判断js数据类型:

let arr = [1, 2, 3];
console.log(typeof arr);            // object
console.log(arr instanceof Object)  // true

因为js中数组被实现成了对象,所随机访问的效率会比其它语言(c或者java)效率低。

什么是链表

上面说了数组,感觉数组用也简单,查找也快,挺方便的。但是数组插入或者删除某个数据的时候,效率就低了,原因是它被设计成必须是连续的内存空间来存储,如果你要删除一个节点,为了不让这个位置空出来,这个位置后面的都需要往前移动一位,添加同理。

数组这种连续的特征可以说是成也萧何败萧何,有得必有舍。我们要做的就是好好利用它的优势,想办法规避它的劣势。js的做法就是取中间,让你访问不会很快,插入,删除也不会很慢,所以js中的数组用对象来实现。

除了js外,其它如c和java语言,就出现了另外一种数据结构,链表它和数组正好相反,它是插入、删除快,新增慢。而且从名字也能看得出来,像一条链一样,中间用一条线连接起来。

举个例子:比如我想找xx市市长办个事,但是我认识市长,市长不认识我,这咋整。此时我发现我七大姑八大姨中有人在政府工作,可能会有点关系,我就问这个亲戚,你有没有认识的人,能和市长搭上关系的,亲戚一想,唉,我xx同学是市长亲戚,于是亲戚去帮你问他同学,他同学在问问市长,安排有时间见一下。

上面这个例子是不可以看成一条线:我 -> 亲戚 -> 亲戚同学 -> 市长。我通过这条线就联系上了市长。
链表就是上面这种关系,链表在内存中不连续,每个节点通过存储下一个节点地址来形成一条完整的链,图如下:

单链表
这种结构相当于在将内存中多个零散的点用一条线来连接起来,好处是插入删除只需要O1的复杂度,看下图:
单链表插入
缺点也很明显,因为是一条链的关系,访问变慢了,只能从头一个个找,查找复杂度达到了On。

链表实现

BB那么多,来点实操。先来看看在js中如何用对象来描述一个链表。

// 链表中,val存贮当前节点值,next存贮下一节点地址,在js中1->2->3->4这条链就可以用如下结构表示
let LinkedList = {
  val: "1",
  next: {
    val: "2",
    next: {
      val: "3",
      next: {
        val: "4",
        next: null,
      },
    },
  },
};
// 就像俄罗斯套娃,一层一层的嵌套就行

总结说明

总结:链表在前端用的地方很少,我网上搜了一圈大致用途是,遇见那种较长的线性表,并且有频繁的插入,删除操作时,可以用链表来提高性能。但是绝大部分情况下还是用数组方便,并且chrome的V8有对数组进行优化,性能很高。

前端链表这种结构,我目前想到的就是刷题的时候用用,并且了解了解它的原理,将来学习其它语言的时候更好上手。

说明:上面链表的两张图来自极客时间课程 算法与数据结构之美