15 Jun 2024
链表是一个数据的集合,其中每个元素包含下 一个元素的地址;即每个元素包含两部分: 数据和链。
链表的每个节点在内存中储存的地址不一定是相连的。链表的一个特点是每个节点除了包含节点数据外,还包含一个指针,指向下一个节点的位置。这意味着链表的节点可以分散在内存中的不同位置,而不需要是连续的。
示例: 链表,有三个节点
在这种情况下,链表在内存中的存储示意图如下:
地址 内容
0x1000 +----------------------------------------------------------+
| data: 00000001 00000000 00000000 00000000 | // 值:1,位模式为小端序
0x1004 | next: 00001000 00100000 00000000 00000000 | // 地址:0x2008,小端序
+----------------------------------------------------------+
|
v
0x2008 +----------------------------------------------------------+
| data: 00000010 00000000 00000000 00000000 | // 值:2,位模式为小端序
0x200C | next: 00001100 00110000 00000000 00000000 | // 地址:0x300C,小端序
+----------------------------------------------------------+
|
v
0x300C +----------------------------------------------------------+
| data: 00000011 00000000 00000000 00000000 | // 值:3,位模式为小端序
0x3010 | next: 00000000 00000000 00000000 00000000 | // 地址:NULL,小端序
+----------------------------------------------------------+
链表的所有操作的空间复杂度都是O(1)
在头部插入:时间复杂度:O(1) 在尾部插入:时间复杂度:O(n)(若有尾指针,可优化到O(1)) 在中间插入:时间复杂度:O(n)(需要遍历到指定位置)
删除头节点:时间复杂度:O(1) 删除尾节点:时间复杂度:O(n)(若有尾指针,可优化到O(1)) 删除中间节点:时间复杂度:O(n)(需要遍历到指定位置)
按值查找:时间复杂度:O(n)(需要遍历整个链表) 按位置查找:时间复杂度:O(n)(需要遍历到指定位置)
访问头节点:时间复杂度:O(1) 访问尾节点:时间复杂度:O(n)(若有尾指针,可优化到O(1)) 访问中间节点:时间复杂度:O(n)(需要遍历到指定位置)
更新指定位置的节点:时间复杂度:O(n)(需要遍历到指定位置)
前面只介绍了经典的单链表类型,其实链表还有很多其他类型: