链表学习初体验

121 阅读2分钟

链表是一种常见的数据结构,用于存储和组织数据。它由一系列节点组成,每个节点包含数据和一个指向下一个节点的引用(指针或链接)。与数组不同,链表中的元素在内存中不必是相邻的,它们通过指针相互连接。

链表分为单向链表和双向链表两种主要类型:(今天我们主要围绕单向链表进行学习)

  1. 单向链表(Singly Linked List): 在单向链表中,每个节点只有一个指针,指向下一个节点。链表的尾节点指向空值(null),表示链表的结束。

    单向链表

  2. 双向链表(Doubly Linked List): 在双向链表中,每个节点有两个指针,一个指向前一个节点,另一个指向后一个节点。这使得在双向链表中可以更方便地在节点之间进行前后移动。

    双向链表

链表相对于数组的优点包括:

  • 动态大小: 链表可以动态地分配内存,而数组需要在开始时确定大小。
  • 插入和删除效率高: 在链表中插入或删除节点比在数组中更为高效,因为不需要移动其他节点。
  • 不需要预分配内存: 链表可以根据需要动态分配内存,而数组需要预分配固定大小的内存。

然而,链表的缺点是访问元素时需要遍历整个链表,而数组可以通过索引直接访问元素,这导致链表在某些操作上效率较低。链表在实际应用中常用于需要频繁插入和删除操作的场景。

接下来我们通过一些代码来更好的理解链表

{
    val: 1,  // 数据域
    next: {  // 指针域
        val: 2,
        next: ... //如此循环
    }
}

function ListNode(val){
    this.val = val
    this.next = null
}
let node = new ListNode(1)
node.next = new ListNode(2)  //让节点1的指针指向节点2
node.next.next = new ListNode(3)//节点2的指针指向节点3

如果要在1,2之间增加一个节点呢?如下

image.png

只需要让节点1的指针指向节点3,再让节点3指向节点2即可。

如果是要删除中间的节点呢?

image.png

let node1 = new ListNode(1)
node1.next = new ListNode(2)
node1.next.next = new ListNode(3)

const target = node1.next   //node1.next表示节点2(节点1的指针指向节点2)
node1.next = target.next    // target.next 表示节点2的指针,指向节点3,你把它赋给了节点1的指针,也就是说此时节点1的指针指向了节点3

数组与链表:

数组中增加或删除一个元素会导致n个元素移动,时间复杂度为O(n)

链表的增删一个元素时间复杂度为O(1)