链表作为基础数据结构,在程序设计与算法面试中占据重要地位。其物理存储的非连续性赋予了它在插入、删除操作上的优势,但也带来了随机访问的挑战。本文精选了十道经典的链表 OJ 题目,从思路分析到 C 语言代码实现,逐步详解快慢指针、哑结点等核心技巧,帮助读者深入理解并掌握链表操作。
1. 删除链表中等于给定值 val 的所有结点
题目描述
删除链表中所有值为 val 的结点,返回删除后的链表头结点。
思路分析 处理链表删除时,头结点可能被删除,直接操作容易出错。创建一个带哨兵位(哑结点)的新链表是个好办法。遍历原链表,将符合条件的节点接到新链表后面。注意尾节点的 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 {
ListNode* prev = ;
ListNode* curr = head;
(curr) {
ListNode* next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
}
prev;
}


