算法基础——链表-CSDN博客
一、排队顺序
题⽬来源:洛⾕
题⽬链接:B3630 排队顺序 - 洛谷
难度系数:★
1. 题目描述
2. 算法原理
本题相当于告诉了我们每⼀个点的后继,使⽤静态链表的存储⽅式能够很好的还原这个队列。
数组中 [1, n] 的下标可以当做数据域,根据题意修改指针域即可。
注意:可以不需要 e[N] 数组,输出下标即可
3. 参考代码
#include <iostream>
using namespace std;
const int N = 1e6 + 10;
int n, h;
int ne[N];
int main()
{
cin >> n;
for(int i = 1; i <= n; i++) cin >> ne[i];
cin >> h;
// 遍历链表
for(int i = h; i; i = ne[i])
{
cout << i << " ";
}
return 0;
}
二、单向链表
题⽬来源:洛⾕
题⽬链接:B3631 单向链表 - 洛谷
难度系数:★
1. 题目描述
2. 算法原理
链表模板题,直接实现⼀个单链表即可。
3. 参考代码
#include <iostream>
using namespace std;
const int N = 1e5 + 10, M = 1e6 + 10;
// 链表
int h, id, e[N], ne[N];
int mp[M]; // mp[i] 用来标记 i 这个元素存在什么位置
int main()
{
int q; cin >> q;
// 初始化
id++;
e[id] = 1;
mp[1] = id;
while(q--)
{
int op, x, y;
cin >> op >> x;
int p = mp[x]; // x 存的位置
if(op == 1) // x 后面插入
{
cin >> y;
id++;
e[id] = y;
ne[id] = ne[p];
ne[p] = id;
mp[y] = id; // 标记 y 这个元素存的位置
}
else if(op == 2) // 查询 x 后面的元素
{
cout << e[ne[p]] << endl;
}
else // 删除 x 后面的元素
{
ne[p] = ne[ne[p]];
}
}
return 0;
}
三、队列安排
题⽬来源:洛⾕
题⽬链接:P1160 队列安排 - 洛谷
难度系数:★★
1. 题目描述
2. 算法原理
频繁的在某⼀个位置之前和之后插⼊元素,因此可以⽤双向循环的链表来模拟。
3. 参考代码
#include <iostream>
using namespace std;
const int N = 1e5 + 10;
// 双向链表
int h, pre[N], ne[N];
bool st[N]; // st[x] 表示 x 这个元素是否已经被删除
int n, m;
int main()
{
cin >> n;
// 初始化
pre[1] = h;
ne[h] = 1;
for(int i = 2; i <= n; i++)
{
int k, p; cin >> k >> p;
if(p == 0)
{
// i 放在 k 的左边
ne[i] = k;
pre[i] = pre[k];
ne[pre[k]] = i;
pre[k] = i;
}
else
{
// i 放在 k 的右边
pre[i] = k;
ne[i] = ne[k];
pre[ne[k]] = i;
ne[k] = i;
}
}
cin >> m;
while(m--)
{
int x; cin >> x;
// 将 x 删除
if(st[x] == true) continue;
ne[pre[x]] = ne[x];
pre[ne[x]] = pre[x];
st[x] = true; // 标记 x 已经被删除
}
for(int i = ne[h]; i; i = ne[i])
{
cout << i << " ";
}
return 0;
}
四、约瑟夫问题
题⽬来源:洛⾕
题⽬链接:P1996 约瑟夫问题 - 洛谷
难度系数:★
1. 题目描述
2. 算法原理
使⽤循环链表模拟即可。
3. 参考代码
#include <iostream>
using namespace std;
const int N = 110;
int n, m;
int ne[N];
int main()
{
cin >> n >> m;
// 创建循环链表
for(int i = 1; i < n; i++) ne[i] = i + 1;
ne[n] = 1;
// 模拟约瑟夫游戏的过程
int t = n;
for(int i = 1; i <= n; i++) // 执行 n 次出圈操作
{
for(int j = 1; j < m; j++) // 让 t 向后移动 m - 1 次
{
t = ne[t];
}
cout << ne[t] << " ";
ne[t] = ne[ne[t]];
}
return 0;
}