C语言链表详解
链表是一种动态数据结构,通过指针连接节点,每个节点包含数据和指向下一个节点的指针。以下是详细解析:
一、核心结构
#include <stdio.h>
#include <stdlib.h>
// 定义节点结构
typedef struct Node {
int data; // 数据域
struct Node* next; // 指针域
} Node;
// 创建头指针
Node* head = NULL;
二、常用操作
- 创建节点
Node* createNode(int data) {
Node* newNode = (Node*)malloc(sizeof(Node));
if (!newNode) {
printf("内存分配失败\n");
exit(1);
}
newNode->data = data;
newNode->next = NULL;
return newNode;
}
- 头部插入
void insertAtHead(int data) {
Node* newNode = createNode(data);
newNode->next = head;
head = newNode;
}
- 尾部插入
void insertAtTail(int data) {
Node* newNode = createNode(data);
if (head == NULL) {
head = newNode;
return;
}
Node* temp = head;
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = newNode;
}
- 指定位置插入
void insertAfter(Node* prevNode, int data) {
if (prevNode == NULL) {
printf("前驱节点不能为空\n");
return;
}
Node* newNode = createNode(data);
newNode->next = prevNode->next;
prevNode->next = newNode;
}
- 删除节点
void deleteNode(int key) {
Node *temp = head, *prev = NULL;
if (temp != NULL && temp->data == key) {
head = temp->next;
free(temp);
return;
}
while (temp != NULL && temp->data != key) {
prev = temp;
temp = temp->next;
}
if (temp == NULL) {
printf("未找到节点\n");
return;
}
prev->next = temp->next;
free(temp);
}
- 遍历链表
void printList() {
Node* temp = head;
while (temp != NULL) {
printf("%d -> ", temp->data);
temp = temp->next;
}
printf("NULL\n");
}
三、使用场景
-
动态内存管理
- 数据量未知时(如实时数据流)
- 内存碎片敏感场景
-
高频插入/删除
- 实现队列/栈(优于数组)
- 任务调度系统
-
复杂数据结构
- 图的邻接表
- 哈希表冲突解决
四、技巧与优化
-
双指针技巧
// 快慢指针找中点 Node* findMiddle() { Node *slow = head, *fast = head; while (fast != NULL && fast->next != NULL) { slow = slow->next; fast = fast->next->next; } return slow; } -
带头节点链表
// 创建哨兵节点简化操作 Node* initList() { Node* dummy = (Node*)malloc(sizeof(Node)); dummy->next = NULL; return dummy; } -
内存优化
- 使用内存池预分配节点
- 批量释放内存
五、注意事项
-
内存泄漏
- 每次
malloc()后必须对应free() - 删除节点时更新指针关系
- 每次
-
空指针检测
void safeInsert(Node* prev, int data) { if (prev == NULL) { printf("无效节点\n"); return; } // 插入操作... } -
循环引用
- 避免节点互相指向形成环
- 使用标记法检测环:
int hasCycle() { Node *slow = head, *fast = head; while (fast && fast->next) { slow = slow->next; fast = fast->next->next; if (slow == fast) return 1; } return 0; }
六、完整示例
int main() {
// 创建链表: 10 -> 20 -> 30
insertAtTail(10);
insertAtTail(20);
insertAtTail(30);
printList(); // 输出: 10 -> 20 -> 30 -> NULL
// 头部插入
insertAtHead(5);
printList(); // 输出: 5 -> 10 -> 20 -> 30 -> NULL
// 删除节点
deleteNode(20);
printList(); // 输出: 5 -> 10 -> 30 -> NULL
// 释放内存
Node* current = head;
while (current != NULL) {
Node* next = current->next;
free(current);
current = next;
}
return 0;
}
七、高级应用
-
双向链表
typedef struct DNode { int data; struct DNode *prev, *next; } DNode;- 支持双向遍历
- 删除操作时间复杂度 $O(1)$
-
循环链表
// 尾节点指向头节点 void makeCircular() { if (head == NULL) return; Node* temp = head; while (temp->next != NULL) { temp = temp->next; } temp->next = head; }
关键要点:
- 操作前始终验证指针有效性
- 复杂操作先画节点关系图
- 使用
valgrind检测内存泄漏 - 优先考虑带头节点的实现方式
14万+

被折叠的 条评论
为什么被折叠?



