1. 链表基础与常见操作解析
链表作为数据结构中的基础类型,在C语言中有着广泛的应用场景。与数组不同,链表通过指针将零散的内存块串联起来,每个节点包含数据域和指针域。这种非连续存储特性使得链表在插入删除操作上具有O(1)时间复杂度优势,但也带来了随机访问效率低下的问题。
1.1 链表节点结构定义
在C语言中,链表节点的典型定义如下:
c复制struct ListNode {
int val; // 数据域
struct ListNode *next; // 指针域
};
这种结构体定义是链表操作的基础,理解指针的指向关系是掌握链表算法的关键。在实际编程中,我们通常会使用typedef简化类型名称:
c复制typedef struct ListNode ListNode;
1.2 虚拟头节点技巧
虚拟头节点(dummy node)是链表问题中的常用技巧,特别是在处理可能修改头节点的情况时。它的核心价值在于:
- 统一处理逻辑:无论头节点是否需要被删除或修改,操作方式保持一致
- 简化边界条件:避免对头节点的特殊处理,减少代码复杂度
- 防止内存泄漏:明确新链表的起始位置,便于内存管理
创建虚拟头节点的标准做法:
c复制ListNode* dummy = (ListNode*)malloc(sizeof(ListNode));
dummy->next = head; // 连接原链表
提示:使用完虚拟头节点后务必记得释放内存,否则会造成内存泄漏
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 链表元素删除实战
2.1 LeetCode 203题解
移除链表中指定值节点的完整实现如下:
c复制ListNode* removeElements(ListNode* head, int val) {
ListNode* dummy = (ListNode*)malloc(sizeof(ListNode));
dummy->next = head;
ListNode* prev = dummy;
ListNode* curr = head;
while (curr != NULL) {
if (curr->val == val) {
prev->next = curr->next;
free(curr); // 释放内存
curr = prev->next; // 更新当前指针
} else {
prev = curr;
curr = curr->next;
}
}
ListNode* newHead = dummy->next;
free(dummy); // 释放虚拟头节点
return newHead;
}
