「这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战」
js是没有内置链表这样的数据结构的,所以一般我们要先创建这种数据结构
看下百度是怎么解释链表的链表
我们来一张图
每个节点的结构是简单的 属性val和next val是信息域 next是指针域(js里的引用地址)
这种结构我们可以很好的对头节点进行操作
如图: 我们每个节点next 都指向下个节点 最后一个节点没有指向则为null
创建一个ListNode
class ListNode {
constructor(val, next) {
this.val = val
this.next = next || null
}
}
生成一个链表
这里我们用数组转成链表的形式,我们只要声明一个数组就可以了
// 数组转链表
function genereteList (arr) {
// 先生成一个头结点
const head = new ListNode()
let cur = head
for (let i = 0; i < arr.length; i++) {
cur.next = {
val: arr[i],
next: null
}
// 指向下个节点 下个节点构建节点
cur = cur.next
}
return head.next
}
那链表转数组呢?怎么处理
functon generateArray(list) {
var cur = list
var arr = []
while(cur) {
arr.push(cur.val)
cur = cur.next
}
return arr
}
这样就可以 通过创建数组 转下获得我们的链表了
var arr = [1, 2, 3]
var list = generateList(arr)
// list: {val: 1, next: {val: 2, next: {val: 3, next: null}}}
下面通过做题逐渐链接链表
合并两个升序的链表
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的
示例:1=>2=>3 2=>3=>4 最后合并成 1=>2=>2=>3=>3=>4
如图是箭头依次比较两个大小的大小 按照如图路径构成新的链表
- 两个链表都是升序的,所以我们可以逐个进行对比 然后把相对小的节点保存
- 1节点排完 我们要 在 2=>3 和2=>3=>4再去排 然后是 3 和 2=>3=>4 去排 依次去排 排到第一个链表被排完后 只剩下第二个链表了 然后我们 在把第二个链表余下部分塞到后面
function mergeSortList(l1, l2) {
// 先创建一个节点存储
var head = new ListNode()
// 上面第二部分 我们需要一个节点来去对应每次比较后的指向
var cur = head
// 当我们cur 走到null的是 也即是l1或者l2走到头是null的时候我们就停下循环步骤了
while(l1 !== null && l2 !== null) {
if (l1.val > l2.val) {
cur.next = l1
l1 = l1.next
} else {
cur.next = l2
l2 = l2.next
}
}
cur.next = l1 === null ? l2 : l1
return head.next
}
上面我们是循环遍历的方法去处理的,递归该怎么处理呢?
- 定义个递归function:对比l1 和 l2 的当前节点val的大小 再对比当前节点val值小的next节点和另一个对比
- 边界条件: l1 或 l2 是 null的时候
function reverseList(l) {
if (l1 === null) {
return l1
} else if (l2 === null) {
return l2
} else if (l1.val < l2.val) {
l1.next = reverseList(l1.next, l2)
return l1
} else {
l2.next = revserseList(l2.next, l1)
return l2
}
}
总结
- 链表的结构
- 数组和链表之间的转换
- 循环遍历的方式: 通过一个中间变量 不断改变中间变量的指向
- 合并两个升序链表
- 通过大小对比,改变节点指针指向
- 链表指针指向的变动的思考