数据结构之链表(js实现)

261 阅读4分钟

一、认识链表

    链表和数组一样是一种线性的数据结构,用于存储一系列元素,但两者的实现机制是完全不同的。链表是一种物理存储单元上非连续、非顺序的存储结构数据元素的逻辑顺序是通过链表中的指针链接次序实现的。

对比数组

数组是最常见的数据结构,但其实数组也有很多缺点:                                                    

    数组的创建是需要占用一段连续的内存空间,并且大小其实是固定的,当你需要对一个数组进行扩容时,要申请另一个段大的内存空间,再把原来的数组内容给复制进去。并且给数组进行插入或删除元素时,往往会伴随着大量的元素位移。(其实在js中的Array类方法虽然简单便捷,但其原理也是这样)

除了数组,用链表也能对一系列数据进行存储,当链表与数组最大的区别在于链表中元素在内存中不需要连续的空间,可以充分利用计算机内存,实现内存动态管理。

链表还有两个优点:链表也不需要确定大小,扩容时不用另外在申请内存。在进行插入和删除操作时,也不用进行元素位移,时间复杂度可以达到O(1),相比于数组效率高。

缺点:链表要访问某一个元素时,需要从头开始访问,直到找到相应元素

什么是链表

链表的结构类似于火车


一个火车头,火车头连接下一个车厢,每节车厢中有乘客,也连接下一节车厢。


链表中的每个节点可以当做每节车厢,节点中的数据可以当做车厢中的乘客,每个节点指向下一个节点,尾部指向null。

二、封装链表

1、封装链表结构

首先我们知道链表一定有头部,而且每个节点中不仅包含数据data,还有指向下一个节点的引用next.所以在链表类中还需封装一个节点类。

代码如下

2、链表相关操作

2.1、append(element)向尾部添加一个新的项

添加时有两种情况:

  • 链表为空,添加的是唯一节点
链表不为空,在最后一个节点后添加一个新的节点

   

2.2、insert(position, element)向链表中的特定位置插入一个新的项

插入也有两种情况

  • 插入位置为第一个节点之后:先让newNode指向this.head(即原来的第一个节点),再让head指向newNode,顺序不能换,否则无法找到第一个节点的地址
  • 插入位置为非第一,需要两个变量current(当前节点)和previous(上个节点),通过position来找的要插入的位置,并获取该位置current,将newNode.next指向current,最后将previous.next指向newNode即完成插入操作(不能换顺序,否则之后无法找到current的地址)


2.3、get(position)获取对应的位置的元素


2.4、indexOf(element)获取元素在链表中的索引,没有该元素则返回-1


2.5、update(position)修改链表中特定位置的节点


2.6、removeAt(position)移除链表中特定位置中的节点

分两种情况

  • 移除第一个节点  this.head 指向第二个节点(即this.head -> this.head.next)
  • 移除非第一个节点  需要两个变量current(当前节点)和previous(上个节点),通过position来找的要删除的位置,之后将previous指向current的下一个节点即可


2.7、remove(element)移除链表中特定的元素的节点

直接调用indexOf方法获取索引,在通过removeAt()即可删除该元素所在节点


2.8、isEmpty()判断链表是否为空,是则返回true,否则false


2.9、toString()以字符串形式输出


3、测试

创建链表实例


输出结果


测试结果无误,链表封装完成!