「这是我参与11月更文挑战的第4天,活动详情查看:2021最后一次更文挑战」
承接上文上文 作为前端来认识下链表认识链表
今天我们通过链表的增删改查进一步熟悉下链表
链表的增
-
在链表的最后加上一个节点: 类似于数组里的push
- 当对于一个空的链表push的时候,直接返回新的节点
- 非空的时候不断循环到最后一个节点 最后一个节点的指针指向新的节点, 然后返回这个链表
function push(list, val) { const node = new ListNode(val) if (list === null) return node let cur = l while (cur.next !== null) { cur = cur.next } cur.next = node return list } -
给链表的某个位置(n)添加上一个节点(val): 类似于数组里的splice的添加的使用
- 循环遍历找到第n个节点,然后 新的节点指向 这个节点, 这个节点的上个节点指向我们的这个新的节点
- 边界的一些处理 当n === 0 添加到头的则 新的节点指向list 当大于list节点长度则添加到最后
- 代码注释里有重点: 因为需要前一个节点所以 遍历到n - 1个 使用n-1的next来确定当前节点
function appendN(l, n, val) { const node = new ListNode(val) if (n === 0) { node.next = l return newNode } let cur = l let i = 0 while (cur.next !== null) { // 这里我们需要前一个节点 所以 第n个节点只用.next 获取 很重要 if (i === n -1) { break } i++ cur = cur.next } if (cur && cur.next) node.next = cur.next cur.next = node return l }虚头: 用于处理头部边界处理,也是重点
function appendN(l, n, val) { const node = new ListNode(val) const head = new ListNode() head.next = l let i = 0 let cur = head while (cur.next !== null) { if (i === n) { node.next = cur.next cur.next = node break } cur = cur.next i++ } if (cur.next === null) { cur.next = node } return head.next }
链表的删
-
删除第n个节点: 类似于数组里 splice 删除的用方法
- 有可能删掉第一个 先创建虚头
- 循环遍历到底n个的前一个(n - 1), 是前一个的指针指向下一个(n.next)即可
- 返回虚头的next
function removeList(l, n) { let head = new ListNode() head.next = l let cur = head let i = 0 while (cur !== null) { if (i === n) { cur.next = cur.next.next break } else { cur = cur.next } i++ } return head.next } -
删除值是val的节点: 类似于数组里filter 过滤掉list里的值是val的节点
- 和删除第n个类似,修改判断
- 如果删除所有,循环到尾部,如果删除一个则break终止遍历
const head = new ListNode() head.next = l let cur = head while (cur) { if (cur.next && cur.next.val === val) { cur.next = cur.next.next } else { cur = cur.next } } return head.next
链表的改
找到第n个节点,修改这个节点的val
function listPatch(l, n, val) {
let i = 0
let cur = l
while (cur !== null) {
if (i === n) {
cur.val = val
break
}
i++
cur = cur.next
}
return l
}
链表的查
- 查询第index个并返回: 类似于数组里find
function listFind(l, index) {
let cur = l
let i = 0
let res = null
while (cur) {
if (index === i) {
res = cur
break
}
i++
cur = cur.next
}
return res
}
- 查找链表里第一个值等于val的 并返回是第几个节点: 类似于数组里findIndex/indexOf
function listFindIndex(l, val) {
let cur = l
let i = 0
while (cur) {
if (cur.val === val) {
break
}
cur = cur.next
i++
}
return cur !== null ? i : -1
}
总结
-
改和查- 相对而言 改和查相对简单,只要了解链表循环遍历,找到我们需求调出循环
-
增和删- 我们这里有几个算法题里经常用到的一些东西
- 当前节点 下个节点 指针的变动
- 虚头的创建,方便解决很多问题
-
这个我们熟悉链表的开始,接下来我们就要开始去做链表的算法了