目录
-
单链表的结构定义
-
初始化链表
-
求链表长度
-
按序号查找节点
-
按值查找节点
-
插入节点
-
删除节点
-
头插法构建链表
-
尾插法构建链表
-
完整代码与总结
1. 单链表的结构定义
单链表的每个节点包含两部分:
-
数据域:存储节点的值(这里是
int
类型)。 -
指针域:指向下一个节点的地址。
typedef struct LNode {
int data; // 数据域
struct LNode *next; // 指针域,指向下一个节点
} LNode, *LinkList; // 别名:LNode 表示节点,LinkList 表示链表头指针
2. 初始化链表
初始化一个空链表,创建头节点并置空指针域。
bool InitList(LinkList &L) {
L = (LNode*)malloc(sizeof(LNode)); // 分配头节点内存
L->next = NULL; // 头节点的指针域置空
return true;
}
3. 求链表长度
遍历链表,统计节点数量(不包含头节点)。
int length(LinkList L) {
int len = 0;
LNode *p = L;
while (p->next != NULL) { // 从头节点开始遍历
p = p->next;
len++;
}
return len;
}
4. 按序号查找节点
找到链表中第 i
个位置的节点(头节点序号为0)。
LNode *GetElem(LinkList L, int i) {
LNode *p = L;
int j = 0;
while (p != NULL && j < i) { // 遍历直到第 i 个节点
p = p->next;
j++;
}
return p; // 返回节点指针,若未找到返回 NULL
}
5. 按值查找节点
找到链表中第一个值为 e
的节点。
LNode *LocateElem(LinkList L, int e) {
LNode *p = L->next; // 从第一个实际节点开始查找
while (p != NULL && p->data != e) {
p = p->next;
}
return p; // 返回节点指针,若未找到返回 NULL
}
6. 插入节点
在链表的第 i
个位置插入新节点。
bool ListInsert(LinkList &L, int i, int e) {
LNode *p = L;
int j = 0;
while (p != NULL && j < i - 1) { // 找到第 i-1 个节点
p = p->next;
j++;
}
if (p == NULL) return false; // 位置不合法
LNode *s = (LNode*)malloc(sizeof(LNode)); // 创建新节点
s->data = e;
s->next = p->next; // 新节点指向原第 i 个节点
p->next = s; // 原第 i-1 个节点指向新节点
return true;
}
7. 删除节点
删除链表中第 i
个节点,并保存其值到 e
。
bool ListDelete(LinkList &L, int i, int &e) { // 注意 e 应为引用类型
LNode *p = L;
int j = 0;
while (p != NULL && j < i - 1) { // 找到第 i-1 个节点
p = p->next;
j++;
}
if (p == NULL || p->next == NULL) return false;
LNode *q = p->next; // q 指向待删除节点
e = q->data; // 保存被删除节点的值
p->next = q->next; // 绕过 q 节点
free(q); // 释放内存
return true;
}
8. 头插法构建链表
从链表头部依次插入节点,输入 9999
结束。
LinkList List_HeadInsert(LinkList &L) {
LNode *s;
int x;
L = (LNode*)malloc(sizeof(LNode)); // 创建头节点
L->next = NULL;
scanf("%d", &x); // 输入第一个值
while (x != 9999) {
s = (LNode*)malloc(sizeof(LNode));
s->data = x;
s->next = L->next; // 新节点指向原第一个节点
L->next = s; // 头节点指向新节点
scanf("%d", &x); // 继续输入
}
return L;
}
9. 尾插法构建链表
从链表尾部依次插入节点,输入 9999
结束。
LinkList List_TailInsert(LinkList &L) {
int x;
L = (LNode*)malloc(sizeof(LNode)); // 创建头节点
LNode *s, *r = L; // r 始终指向尾节点
scanf("%d", &x);
while (x != 9999) {
s = (LNode*)malloc(sizeof(LNode));
s->data = x;
r->next = s; // 尾节点的 next 指向新节点
r = s; // r 更新为新尾节点
scanf("%d", &x);
}
r->next = NULL; // 尾节点指针置空
return L;
}
10. 完整代码与总结
以下是完整的单链表实现代码:
#include<stdio.h>
#include <cstdlib>
typedef struct LNode {
int data;
struct LNode *next;
} LNode, *LinkList;
// 此处插入上述所有函数实现
int main() {
LinkList L;
InitList(L); // 初始化链表
// 示例:尾插法插入数据 1, 2, 3
List_TailInsert(L); // 输入 1 2 3 9999
// 插入节点到第2个位置(值为10)
ListInsert(L, 2, 10);
// 删除第3个节点
int deletedValue;
ListDelete(L, 3, deletedValue);
cout << "Deleted value: " << deletedValue << endl;
return 0;
}
总结
-
单链表的优势:
-
动态内存分配,无需预先知道数据规模。
-
插入和删除操作的时间复杂度为 O(1)(找到位置后)。
-
-
注意事项:
-
操作时需正确处理指针的指向关系。
-
避免内存泄漏(每次
malloc
后需free
)。
-