1. 为什么链表操作总让人头大?
第一次接触链表时,我也被那些跳来跳去的指针搞得晕头转向。直到在LeetCode上刷到第707题,才真正理解链表操作的精髓。链表不像数组那样有连续的内存空间,它的每个节点都像火车站里分散的候车室,必须通过指针这个"引导员"才能找到下一个位置。
初学者常犯的错误主要有三种:一是忘记处理头节点特殊情况,导致空指针异常;二是在插入/删除时断链,就像拆掉两节车厢的中间连接器却忘了重新挂钩;三是循环引用让链表变成"贪吃蛇",程序陷入死循环。这些痛点在我第一次实现链表时全都踩过,特别是当需要处理头节点时,总是要多写一堆边界条件判断。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 单链表 vs 双向链表:结构差异与实现要点
2.1 单链表基础实现
单链表就像单向行驶的地铁线路,每个站点(节点)只记录下一站的位置。用Python实现时通常会这样定义节点类:
python复制class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
关键操作的时间复杂度:
- 访问:O(n) 必须从头遍历
- 插入/删除:O(1) 如果已知前驱节点
- 搜索:O(n) 需要完整遍历
注意:单链表插入新节点时,一定要先让新节点指向后继,再断开原链接。就像接水管,必须先接好新的再拆旧的,否则会"漏水"(丢失节点引用)。
2.2 双向链表特性解析
双向链表则像双向行驶的BRT车道,每个站点都知道前后两站的位置。节点定义会多一个prev指针:
python复制class DoublyListNode:
def __init__(self, val=0, prev=None, next=None):
self.val = val
self.prev = prev
self.next = next
相比单链表的优势:
- 可以反向遍历
- 删除操作更高效(不需要找前驱)
- 实现LRU缓存等场景更合适
代价则是:
- 每个节点多消耗一个指针空间
- 插入/删除时需要维护两个方向的指针
