单链表
题目:单链表的基本操作
题目描述
实现一个单链表,并支持以下三种操作:
- 将一个元素插入到链表的头部。
- 将一个元素插入到链表中指定元素的后面。
- 删除链表中指定元素的后一个元素。
链表初始为空。每个操作保证合法,且不会删除链表中不存在的元素。
输入格式
第一行包含一个整数 m,表示操作的次数。
接下来 m 行,每行包含一个操作指令,具体形式如下:
H x:将整数x插入到链表的头部。D k:删除链表中第k个元素的后一个元素(k从 1 开始)。I k x:将整数x插入到链表中第k个元素的后面(k从 1 开始)。
输出格式
输出一行,表示最终链表中的所有元素,按顺序用空格隔开。
输入输出示例
示例1
输入1
2
3
4
5
65
H 1
H 2
I 2 3
D 1
I 1 4
输出1
2 4 3
示例2
输入1
2
3
4
54
H 10
H 20
I 1 30
D 2
输出1
20 10
题目分析
我们使用一个数组 e 存储链表的元素,数组 ne 存储每个节点的下一个节点的下标。head 存储链表头部节点的下标,idx 表示当前插入元素的下标。具体实现包括初始化链表、在头部插入元素、在指定位置插入元素,以及删除指定位置后的元素。
通过解析输入的操作指令,我们对链表进行相应的操作,最终输出链表中的所有元素。
这段代码实现了一个简单的单链表操作,包括在头部插入节点、在某个节点后插入节点、删除某个节点后的节点以及遍历链表。
代码解释
定义常量和变量:
1
2const int N = 100010;
int head, e[N], ne[N], idx;N是数组的最大大小。head是链表的头指针。e数组存储节点的值。ne数组存储每个节点的下一个节点的索引。idx是当前节点的索引。
初始化函数:
1
2
3
4void init() {
head = -1;
idx = 0;
}初始化链表,将
head设为-1表示链表为空,idx设为0。在头部插入节点:
1
2
3
4
5
6void add_to_head(int x) {
e[idx] = x;
ne[idx] = head;
head = idx;
idx++;
}将值
x插入到头部节点,更新头指针和idx。在节点
k后插入节点:1
2
3
4
5
6void add(int k, int x) {
e[idx] = x;
ne[idx] = ne[k];
ne[k] = idx;
idx++;
}在节点
k后插入值x的新节点。删除节点
k后的节点:1
2
3void remove(int k) {
ne[k] = ne[ne[k]];
}删除节点
k后的节点。主函数:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24int main() {
int m;
cin >> m;
init();
while (m--) {
int k, x;
char op;
cin >> op;
if (op == 'H') {
cin >> x;
add_to_head(x);
} else if (op == 'D') {
cin >> k;
if (!k) head = ne[head];
remove(k - 1);
} else {
cin >> k >> x;
add(k - 1, x);
}
}
for (int i = head; i != -1; i = ne[i]) cout << e[i] << ' ';
cout << endl;
return 0;
}- 读取操作数量
m。 - 初始化链表。
- 循环处理每个操作,根据操作类型执行相应的链表操作。
- 最后遍历并输出链表中的所有节点值。
- 读取操作数量
处理流程示例
假设输入如下:
1 | 5 |
输入解释
- 第1行:
5表示有5个操作。 - 第2行:
H 3在头部插入值为3的节点。 - 第3行:
H 2在头部插入值为2的节点。 - 第4行:
I 1 4在第1个节点后插入值为4的节点。 - 第5行:
D 2删除第2个节点后的节点。 - 第6行:
H 1在头部插入值为1的节点。
按照代码处理流程
初始化链表:
1
2head = -1;
idx = 0;执行操作:
操作
H 3:1
add_to_head(3);
更新后
e = [3],ne = [-1],head = 0,idx = 1。操作
H 2:1
add_to_head(2);
更新后
e = [3, 2],ne = [-1, 0],head = 1,idx = 2。操作
I 1 4:1
add(0, 4);
更新后
e = [3, 2, 4],ne = [2, 0, -1],head = 1,idx = 3。操作
D 2:1
remove(1);
更新后
ne = [2, -1, -1]。操作
H 1:1
add_to_head(1);
更新后
e = [3, 2, 4, 1],ne = [2, -1, -1, 1],head = 3,idx = 4。
遍历并输出链表:
1
for (int i = head; i != -1; i = ne[i]) cout << e[i] << ' ';
从头指针
head = 3开始遍历,输出结果为:1
1 2
总结
通过这个例子,可以看到如何按照输入操作动态地更新链表,并最终输出链表的内容。每个操作都按照代码中的逻辑逐步进行,链表结构在每一步都进行了相应的更新和调整。