算法标签 链表

题目描述

实现一个单链表,链表初始为空,支持三种操作:

(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++;
}

[模板题]单链表_链表_02

在指定的位子K后添加节点K:

在e[idx]保存值t,当前节点idx指向节点K指向的节点,节点K指向当前节点,当前节点值向后滚动+1.

[模板题]单链表_链表_03

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],head,idx;

void del(int x)
{
ne[x]=ne[ne[x]];
}

void add_h(int x)
{
e[idx]=x,ne[idx]=head,head=idx++;
}

void add_k(int k,int x)
{
e[idx]=x,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;
}