前言
链表是数据结构中的基础,也是面试高频考点。相比数组,链表在插入删除上更灵活,但随机访问较弱。掌握链表的常见操作和经典问题的解法,是每个程序员必备的技能。本文精选了 10 道经典的链表 OJ 题目,从思路分析到 C 语言代码实现,逐步详解,并穿插了快慢指针、哑结点等常用技巧的讲解。
1. 移除链表元素
题目描述 删除链表中所有值为 val 的结点,返回删除后的链表头结点。
核心思路 处理链表头部节点可能需要被删除的情况比较麻烦,这里推荐使用哨兵节点(哑结点)。创建一个新节点作为虚拟头结点,将符合条件的节点接到新链表后面,最后返回虚拟头结点的 next 节点。注意尾节点的 next 需要置为 NULL,如果原链表为空则直接返回空。
参考实现
typedef struct ListNode ListNode;
struct ListNode* removeElements(struct ListNode* head, int val) {
if(head == NULL) return NULL;
ListNode* newhead = (ListNode*)malloc(sizeof(ListNode));
ListNode* newtail = newhead;
ListNode* pcur = head;
while(pcur) {
if(pcur->val != val) {
newtail->next = pcur;
newtail = newtail->next;
}
pcur = pcur->next;
}
newtail->next = NULL;
return newhead->next;
}
2. 反转链表
题目描述 反转一个单链表,返回反转后的链表头结点。
核心思路 迭代法是最常用的方式。使用三个指针 prev、curr、next。初始时 prev 为 NULL,curr 指向头结点。每次将 curr->next 指向 prev,然后三个指针整体后移,直到 curr 为 NULL,此时 prev 即为新头结点。注意保存下一个节点防止断链。
参考实现
typedef struct ListNode ListNode;
struct ListNode* reverseList(struct ListNode* head) {
ListNode* n1 = NULL, *n2 = head, *n3 = head ? head->next : ;
(n2) {
n2->next = n1;
n1 = n2;
n2 = n3;
(n3) n3 = n3->next;
}
n1;
}


