链表特点
1. 有序的列表
2. 线性的结构
3. 所有的结点都是离散分布的
如图:
咱把结点单独拿出来,状态是这样的:
-
表里有数字的为val,是结点当中的值
-
有箭头的为next,是指向下一个结点的指针 **
4. 访问链表中任何一个结点,都要从头结点开始逐个查找** 这个我们看链表在JavaScript中的表示:
let lb = {
val: 1,
next: {
val: 2,
next: {
val: 3,
next: {
val: 4,
next: nul
}
}
}
}
跟洋葱一样一层一层的
- 插入一个结点
当我们想在结点3,4中添加一个结点6,步骤应该为:
1.删除3指向4的指针
2.让3的指针指向6
3.让6的指针指向4
用代码表示为:
function ListNode(val) {
this.val = val
this.next = null
}//定义链表
const node = new ListNode(1)
const node2 = new ListNode(2)
const node3 = new ListNode(3)
const node4 = new ListNode(4)
const node5 = new ListNode(5)//创建结点
//添加结点
const node6 = new ListNode(6)
node6.next = node4
node3.next = node6
- 移除一个节点
比如我们想删掉结点2,步骤为:
1.删掉指向2的指针,也就是1的next
2.把原本指向2的指针(1的next)指向2之后的结点3
node.next = node2
node2.next = node3
node.next = node3
代码为:
- 头部增加节点:
创建一个节点,新创建的结点指针指向链表第一位
- 尾部增加节点:
一路找,找到链表尾部的结点然后再让它的指针指向这个新结点
- 遍历数组查值:
const index = 10
let node = head
for (let i = 0; i < index && node; i++) {
node = node.next
}
链表VS数组
数组
数组在绝大多数计算机语言中,数组都是一段连续的内存,如果我们想要移除一个元素的话,增删元素就会变得很麻烦。随着数组的长度(n)增加,增删操作所带来的需要移动的元素个数也会随之增加。(可以想象一下打麻将时候的摸牌和出牌)
这个操作的时间复杂度为O(n)
链表
对于增删操作,链表就显得简单得多,它甚至没有时间复杂度(为O(1)),只需要改一下对应指针就可以了。
所以我们可以总结出:
5. 相比数组,数组中增加或者删除一个元素,会导致需要移动n个元素,时间复杂度为O(n)。链表的增加和删除元素不需要移动其他元素O(1)
6. 链表查找元素的时间复杂度为O(n),而数组查找元素的时间复杂度为O(1)
实战
打开力扣咱们来写题目
代码:
var mergeTwoLists = function (list1, list2) {
let head = new ListNode()
let cur = head //保留head结点
while (list1 && list2) {//两链表都有值
//比较节点的值
if (list1.val <= list2.val) {
//list1的值小于list2
cur.next = list1//头结点用list1的
list1 = list1.next//list1 现在从第二个结点开始
} else {//list2更小
cur.next = list2//头结点用list2的
list2 = list2.next
}
cur = cur.next //每循环一次,cur都要代表下一个结点,cur最后代表的是结尾的结点
}
if(list1){//最后两个链表可能会有一个链表还没有合并到,还有的结点没走到
cur.next = list1//因为链表是有序的,后面的结点不用再判断了
}else{
cur.next = list2
}//这段可以用三元运算符写成cur.next = list1 !== null ? list1 : list2
return head.next
};
LCR 136. 删除链表的节点 - 力扣(LeetCode)
var deleteNode = function(head, val) {
let cur = head;
if (cur.val === val) {//要移除的是头结点
head = head.next
}
while (cur && cur.next) {
if (cur.next.val === val) {
// cur就是要被移除的节点
cur.next = cur.next.next;
}
// 当前节点的下一个节点与当前节点的值不相等,继续向后遍历
cur = cur.next;
}
return head;
};
83. 删除排序链表中的重复元素 - 力扣(LeetCode)
var deleteDuplicates = function(head) {
let cur = head;
while (cur && cur.next) {//有值
if (cur.val === cur.next.val) {//有重复的元素
cur.next = cur.next.next; //更改指针
} else {
cur = cur.next;//没有重复值咱就继续看下一个
}
}
希望本文对读者理解链表的特点、操作方法以及实际应用有所帮助!如果有任何其他问题,欢迎随时提问。