前言
链表(Linked List)是一种数据结构,它由一系列节点组成,每个节点包含数据和一个指向下一个节点的引用。JavaScript中实现链表可以使用对象来表示节点,并通过对象的引用建立节点之间的连接。在本文中我们将介绍链表的概念,基本特性。以及如何使用链表去解决一些算法题。
正文
[ ] 链表是一个有序的列表,其具有线性的结构
链表由一系列结点组成,每个结点存储着值和指针,它们的指针都指向下一个结点
//链表代码实现
let lb = {
val: 1,
next: {
val: 2,
next:{
val:3,
next:{
val:4,
next: null
}
}
}
}
这段代码实现一个链表,这个链表里面有4个结点,分别存储着1,2,3,4。由于每个结点都只和它们下一个结点有关系,那么我们该怎么去访问链表里面的结点呢?
lb.next.next.val我们要想访问第三个结点就只能顺着第一个结点访问到第二个结点,然后通过第二个结点来访问第三个结点。那么要想访问第四个结点我们只需要以此类推lb.next.next..next.val,再加一个.next就行了
在这里我们需要了解的知识点是:
1.所有的节点都是离散分布的
2.访问链表中任何一个节点,都要从头结点开始逐个查找
[ ] 如何在链表中实现增加,删除,查找操作?
-我们已经知道链表都用指针指向下一个结点,所以当我们想增加一个结点时只需要将增加的位置的上一个结点的指针指向增加的结点的值,然后再让增加的结点的指针指向下一个结点的值就完成了增加的操作
//增加节点
function ListNode(val){
this.val = val
this.next = null
}
const node = new ListNode(1)
const node2= new ListNode(2)
node.next = node2
const node3= new ListNode(3)
node3.next = node2
node1.next = node3
在这段代码中我们定义了一个名为ListNode的构造函数,用于创建链表中的节点。val: 存储节点的值。
next: 初始化为null,用于指向链表中的下一个节点。这段代码实现了增加结点的操作。
—-同理,如果我们想要删除一个结点的话,我们无需理会要删除的那个结点,只需要将目标结点的上一个结点指针指向下一个结点的值就行了。
//删除结点
const node = new ListNode(1)
const node2= new ListNode(2)
const node3= new ListNode(3)
node.next = node2
node2.next = node3
node.next = node3
因此我们要明白相比数组,数组中增加或者删除一个元素,会导致需要移动n个元素,时间复杂度为O(n)。 链表的增加和删除元素不需要一定其他元素,时间复杂度为(1)。这是链表的优点
- 链表的查找操作
let head = {
}
const index = 10
let node = head
for (let i = 0; i < index && node; i ++){
node = node.next
}
我们定义了一个空对象head,表示链表的头结点。如果我们想要查找第十个结点的值在这里会进入一个for循环,条件是i < index且node非空。在每次循环迭代中,node被更新为node.next,即移动到链表中的下一个节点。循环会执行10次最终node将会指向链表中的最后一个结点。如果链表没有那么长,node最终会是null,表示已经到达了链表的末尾。因为for循环要执行10次,所以时间复杂度为O(n)。
链表查找元素的时间复杂度为O(n),而数组查找元素只需要访问目标值的位置,时间复杂度为O(1)
总结
在本文中我们介绍了链表的概念以及如何在链表中执行增加,删除,查找的操作。以及链表与数组相比的优点与缺点。我们将在介绍如何使用链表解决LeetCode中的算法题。如果本文对大家有帮助的话,点赞收藏点起来吧 : )