文章目录
- [0. 注意](#0. 注意)
- [1. 排队顺序(链表的打印)](#1. 排队顺序(链表的打印))
- [2. 排队顺序(单链表)](#2. 排队顺序(单链表))
- [3. 队列安排(双向链表)](#3. 队列安排(双向链表))
- [4. 约瑟夫问题(循环链表)](#4. 约瑟夫问题(循环链表))
0. 注意
new 和 delete 是非常耗时的操作,
在算法比赛中,一般不会使用 new 和 delete 去模拟实现一个链表。
而 STL 里面的 list 的底层就是动态实现的双向循环链表,增删会涉及 new 和 delete,效率不高,竞赛中一般不会使用,而是以静态实现的方式。
关于链表的静态实现 可以参考我写的博客 点击转跳
1. 排队顺序(链表的打印)
https://www.luogu.com.cn/problem/B3630#ide
本题相当于告诉了我们每一个点的后继,使用静态链表的存储方式能够很好的还原这个队列。数组中 [1,n] 的下标可以当做数据域,根据题意修改指针域即可。
cpp
#include<bits/stdc++.h>
using namespace std;
int n,h,i;
const int N=1e6+10;
int main()
{
cin>>n;
int ne[N];
for(i=1;i<=n;i++)
{
cin>>ne[i];
}
cin>>h;
for(i=h; i;i=ne[i])
{
cout<< i <<" ";
}
return 0;
}
2. 排队顺序(单链表)
https://www.luogu.com.cn/problem/B3631

链表模板题,直接实现⼀个单链表即可!!
cpp
#include<bits/stdc++.h>
using namespace std;
int h, id;
const int N=1e6+10;
int e[N],ne[N],mp[N],q,op,x,y;
int main()
{
id++;
e[id]=1;
ne[h]=1;
mp[1]=id;
cin>>q;
for(int i=0;i<q;i++)
{
cin>>op>>x;
if(op==1)
{
cin>>y;
id++;
e[id]=y;
ne[id]=ne[mp[x]];
ne[mp[x]]=id;
mp[y]=id;
}
if(op==2)
{
cout<<e[ne[mp[x]]]<<endl;
}
if(op==3)
{
if(ne[mp[x]])
{
// mp[e[ne[mp[x]]]]=0;
ne[mp[x]]=ne[ne[mp[x]]];
}
}
}
return 0;
}
3. 队列安排(双向链表)
https://www.luogu.com.cn/problem/P1160

频繁的在某⼀个位置之前和之后插⼊元素,因此可以⽤双向循环的链表来模拟。
循环双链表的静态实现可以参考我的博客 点击转跳
cpp
#include<bits/stdc++.h>
using namespace std;
const int N =1e5+10;
int h,id,k,p,M,x;
int ne[N],mp[N],pre[N];
int main()
{
int num;
ne[0]=1;
pre[1]=0;
mp[1]=1;
id++;
cin>>num;
for(int i=2;i<=num ;i++)
{
cin>>k>>p;
id++;
mp[i]=id;
if(p==1)
{
ne[id]=ne[k];
pre[id]=mp[k];
pre[ne[mp[k]]]=id;
ne[mp[k]]=id;
}
else
{
ne[id]=mp[k];
pre[id]=pre[mp[k]];
ne[pre[mp[k]]]=id;
pre[mp[k]]=id ;
}
}
cin>>M;
while(M--)
{
cin>>x;
if(mp[x])
{
ne[pre[mp[x]]]=ne[mp[x]];
pre[ne[mp[x]]]=pre[mp[x]];
mp[x]=0;
}
}
for(int j = ne[h];j;j=ne[j])
{
cout<<j<<" ";
}
return 0;
}
4. 约瑟夫问题(循环链表)
https://www.luogu.com.cn/problem/P1996

使⽤循环链表模拟即可! 但是这里面有一些小细节 我们删除元素的时候 每走
m-1次就删除后面的元素 (比如给的测试样例是每走3次删一个元素,我们每数2次就删除它后面的元素),这是因为单链表删除有个关键的步骤是ne[删除元素的前一个元素的位置]=ne[ne[删除前一个元素的位置]]如果我们直接删除当前元素,就很难找到当前元素的前一个位置!
cpp
#include<bits/stdc++.h>
using namespace std;
const int N =110;
int n,m;
int h,id;
int ne[N];
int main()
{
cin>>n>>m;
//创建循环链表
for(int i=1;i<n;i++)
{
ne[i]=i+1;
}
ne[n]=1;
//用t指针进程模拟
int t=n;//从1开始报数,那么t初始位置就该在最后
while(n--)
{
for(int i=1;i<m;i++)
{
t=ne[t];
}
cout<<ne[t]<<" ";
ne[t]=ne[ne[t]];
}
return 0;
}
