来源: 模板题
算法标签 链表
题目描述
实现一个单链表,链表初始为空,支持三种操作:
(1) 向链表头插入一个数;
(2) 删除第k个插入的数后面的数;
(3) 在第k个插入的数后插入一个数
现在要对该链表进行M次操作,进行完所有操作后,从头到尾输出整个链表。
注意:题目中第k个插入的数并不是指当前链表的第k个数。例如操作过程中一共插入了n个数,则按照插入的时间顺序,这n个数依次为:第1个插入的数,第2个插入的数,…第n个插入的数。
输入格式
第一行包含整数M,表示操作次数。
接下来M行,每行包含一个操作命令,操作命令可能为以下几种:
(1) “H x”,表示向链表头插入一个数x。
(2) “D k”,表示删除第k个输入的数后面的数(当k为0时,表示删除头结点)。
(3) “I k x”,表示在第k个输入的数后面插入一个数x(此操作中k均大于0)。
输出格式
共一行,将整个链表从头到尾输出。
数据范围
1≤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
#### 思路
为什么用静态数组模拟链表?
用静态数组模拟链表操作可以将访问从动态的o(n)压到o(1);
在比赛中常牺牲部分空间来换取时间的高效。
删除第t个数据:
将当前位置的连接数组,连接到对应的连接数组的连接数组。
void del(int t)
{
ne[t]=ne[ne[t]];
}
在第K的位置添加节点t
在e[idx]保存值t,当前节点idx指向头节点指向的数值,头节点指向当前节点,当前节点值向后滚动+1.
void add_h(int t)
{
e[idx]=t,ne[idx]=head,head=idx++;
}
在指定的位子K后添加节点K:
在e[idx]保存值t,当前节点idx指向节点K指向的节点,节点K指向当前节点,当前节点值向后滚动+1.
void add_k(int k,int t)
{
e[idx]=t,ne[idx]=ne[k],ne[k]=idx++;
}
C++ 代码
#include<iostream>
using namespace std;
const int N=1e5+10;
int e[N],ne[N],idx,head;//e值.ne指针指向,idx当前节点,head头节点
void del(int t)
{
ne[t]=ne[ne[t]];
}
void add_h(int t)
{
e[idx]=t,ne[idx]=head,head=idx++;//head=idx++ idx++是后缀表达式,实际会head=idx赋值完毕之后执行idx++
}
void add_k(int k,int t)
{
e[idx]=t,ne[idx]=ne[k],ne[k]=idx++;
}
int main()
{
int n;
cin>>n;
head=-1;//初始化 head=-1,idx=0; 因为idx全局默认为0,head为-1实质上-1会排在最末用以终结链表
char g;int t,k;
while(n--)
{
cin>>g;
if(g=='H')
{
cin>>t;
add_h(t);
}
else if(g=='D')
{
cin>>k;
if(!k)head = ne[head];
else del(k-1);
}
else
{
cin>>k>>t;
add_k(k-1,t);//因为下标从0开始,所以第k实质为k-1.
}
}
for(int i=head;i!=-1;i=ne[i])cout<<e[i]<<" ";//按找链表指针方式进行更新
return 0;
}