[路飞_链表]前端XDM 我们也来认识下链表

508 阅读2分钟

「这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战

js是没有内置链表这样的数据结构的,所以一般我们要先创建这种数据结构

看下百度是怎么解释链表的链表

我们来一张图

每个节点的结构是简单的 属性valnext val是信息域 next是指针域(js里的引用地址)

这种结构我们可以很好的对头节点进行操作

未命名文件.png 如图: 我们每个节点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).png

  • 两个链表都是升序的,所以我们可以逐个进行对比 然后把相对小的节点保存
  • 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
    }
}

总结

  • 链表的结构
  • 数组和链表之间的转换
    • 循环遍历的方式: 通过一个中间变量 不断改变中间变量的指向
  • 合并两个升序链表
    • 通过大小对比,改变节点指针指向
  • 链表指针指向的变动的思考