题目描述:
实现一个单链表,链表初始为空,支持三种操作:
- 向链表头插入一个数;
- 删除第 k个插入的数后面的一个数;
- 在第 k 个插入的数后插入一个数。
现在要对该链表进行 MM 次操作,进行完所有操作后,从头到尾输出整个链表。
注意:题目中第 kk 个插入的数并不是指当前链表的第 kk 个数。例如操作过程中一共插入了 nn 个数,则按照插入的时间顺序,这 nn 个数依次为:第 11 个插入的数,第 22 个插入的数,…第 nn 个插入的数。
输入格式
第一行包含整数 MM,表示操作次数。
接下来 MM 行,每行包含一个操作命令,操作命令可能为以下几种:
H x
,表示向链表头插入一个数 xx。D k
,表示删除第 kk 个插入的数后面的数(当 kk 为 00 时,表示删除头结点)。I k x
,表示在第 kk 个插入的数后面插入一个数 xx(此操作中 kk 均大于 00)。
输出格式
共一行,将整个链表从头到尾输出。
数据范围
1≤M≤1000001≤M≤100000
所有操作保证合法。
输入样例:
10
H 9
I 1 1
D 1
D 0
H 6
I 3 6
I 4 5
I 4 5
I 3 4
D 6
输出样例:
6 4 6 5
分析
1.初始化,ne[ ]表示该节点指向的下一个位置,n[ ]表示该节点的值,idx表示最新输入的是第几个节点,head是一个特殊的ne[ ],指向第一个节点,初始值为-1,表示集合为空。
#include <iostream>
using namespace std;
const int N = 100010;
int n;
int h[N], e[N], ne[N], head, idx;
//对链表进行初始化
void init(){
head = -1;//最开始的时候,链表的头节点要指向-1,
//为的就是在后面进行不断操作后仍然可以知道链表是在什么时候结束
/*
插句题外话,我个人认为head其实就是一个指针,是一个特殊的指针罢了。
刚开始的时候它负责指向空结点,在链表里有元素的时候,它变成了一个指向第一个元素的指针
当它在初始化的时候指向-1,来表示链表离没有内容。
*/
idx = 0;//idx在我看来扮演两个角色,第一个是在一开始的时候,作为链表的下标,让我们好找
//第二在链表进行各种插入,删除等操作的时候,作为一个临时的辅助性的所要操作的元素的下
//标来帮助操作。并且是在每一次插入操作的时候,给插入元素一个下标,给他一个窝,感动!
/*
再次插句话,虽然我们在进行各种操作的时候,元素所在的下标看上去很乱,但是当我们访问的
时候,是靠着指针,也就是靠ne[]来访问的,这样下标乱,也就我们要做的事不相关了。
另外,我们遍历链表的时候也是这样,靠的是ne[]
*/
}
2.向链表头插入一个数x:ne[idx] = head, head = idx, e[idx] = x, idx++;
void int_to_head(int x){//和链表中间插入的区别就在于它有head头节点
e[idx] = x;//第一步,先将值放进去
ne[idx] = head;//head作为一个指针指向空节点,现在ne[idx] = head;做这把交椅的人换了
//先在只是做到了第一步,将元素x的指针指向了head原本指向的
head = idx;//head现在表示指向第一个元素了,它不在是空指针了。(不指向空气了)
idx ++;//指针向下移一位,为下一次插入元素做准备。
}
3.删除第 k 个插入的数后面的数: ne[k] = ne[ne[k]]
//将下标是k的点后面的点个删掉
void remove(int k){
ne[k] = ne[ne[k]];//让k的指针指向,k下一个人的下一个人,那中间的那位就被挤掉了。
}
4.在第 k 个插入的数后插入一个数x: e[idx] = x, ne[idx] = n[k], n[k] = idx, idx++;
//将x插入到下标为k的点的后面
void add(int k, int x){
e[idx] = x;//先将元素插进去
ne[idx] = ne[k];//让元素x配套的指针,指向它要占位的元素的下一个位置
ne[k] = idx;//让原来元素的指针指向自己
idx ++;//将idx向后挪
}
代码
int main(){
cin >> n;
int();//初始化
for (int i = 0; i < n; i ++ ) {
char s;
cin >> s;
if (s == 'H') {
int x;
cin >> x;
int_to_head(x);
}
if (s == 'D'){
int k;
cin >> k;
if (k == 0) head = ne[head];//删除头节点
else remove(k - 1);//注意删除第k个输入后面的数,那函数里放的是下标,k要减去1
}
if (s == 'I'){
int k, x;
cin >> k >> x;
add(k - 1, x);//同样的,第k个数,和下标不同,所以要减1
}
}
for (int i = head; i != -1; i = ne[i]) cout << e[i] << ' ' ;
cout << endl;
return 0;
}