双链表
双向链表也叫双链表,是链表的一种,它的每个数据节点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个节点开始,都可以很方便地访问它的前驱节点和后继节点。一般我们都构造双向循环链表。
图解:(e[x] 记录所存的值,l[x] 记录左指针所指向的节点,r[x] 记录右指针指向的节点)
初始化
双链表在初始化的时候可以直接简写,使 0 节点为左端点,1 节点为右端点即可
图解:(即 0 节点作为头节点,1 节点作为尾节点)
代码表示:(idx记录当前处理的节点的编号)
// 初始化
void init()
{
r[0] = 1; // 0号点的右边是1
l[1] = 0; // 1号点的左边是0
idx = 2; // 因为之前两个点已经使用过,所以从2开始处理
}
基本操作
插入
"在 k 节点的右边插入一个节点 x"
操作步骤
1、首先将x节点的右指针指向k节点的右边的节点
2、将x节点的左值针指向k节点
3、将x节点的右边的节点的左指针指向x节点
4、将x节点的右指针指向x节点
(3,4不可变换顺序,如果先执行4,会改变初始值,影响交换)
图解:
代码表示:
void add(int k, int x){
e[idx] = x; // 首先赋值到当前节点
r[idx] = r[k]; // 将 x 节点的右指针指向 k 节点的右节点
l[idx] = k; // 将 x 节点的左指针指向 k 节点
l[r[k]] = idx; // 将 k 节点的右节点的左指针指向 x
r[k] = idx; // 将 k 节点的左指针指向 x
idx ++;
}
"如果想要在 k 节点的左边插入一个节点,那么就相当于在 k 节点的左节点的右侧插入一个节点,即 ‘add(l[k], x)’ "
删除
"删除 k 节点"
操作步骤
1、将 k 节点的右节点的左指针指向 k 节点的左节点
2、将 k 节点的左节点的右指针指向 k 节点的右节点
图解:
代码表示:
// 删除节点k
void remove(int k)
{
l[r[k]] = l[k]; // 将 k 节点的右节点的左指针指向 k 节点的左节点
r[l[k]] = r[k]; // 将 k 节点的左节点的右指针指向 k 节点的右节点
}
题目
题目链接
https://www.acwing.com/problem/content/829/
AC代码
学算法就上AcWing!!!
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100010;
// l[] 表示左边结点的值
// r[] 表示右边结点的值
// e[] 表示当前结点的值
// idx 表示当前处理的结点
int l[N], r[N], e[N], idx;
void init()
{
r[0] = 1; // 0号点的右边是1
l[1] = 0; // 1号点的左边是0
idx = 2; // 因为之前两个点已经使用过,所以从2开始处理
}
// 在 k 的右边插入一个结点 x
void insert(int k,int x)
{
e[idx] = x; // 将 x 的值赋值到 e 数组之中
r[idx] = r[k]; // 将x结点的右指针指向k结点的右边的结点
l[idx] = k; // 将x结点的左值针指向k结点
l[r[k]] = idx; // 将x结点的右边的结点的左指针指向x结点
r[k] = idx; // 将x结点的右指针指向x结点
idx ++;
}
// 删除 k 结点的右结点
void remove(int k)
{
l[r[k]] = l[k]; // 将 k 结点的左结点指向 k 结点的右结点
r[l[k]] = r[k]; // 将 k 结点的右结点指向 k 结点的左结点
}
int main()
{
int t;
cin >> t;
init();
while( t -- )
{
string op;
int n, m;
cin >> op;
if(op == "L")
{
cin >> n;
insert(0, n);
}
else if(op == "R")
{
cin >> n;
insert(l[1], n);
}
else if(op == "D")
{
cin >> n;
remove(n + 1);
}
else if(op == "IL")
{
cin >> n >> m;
insert(l[n + 1],m);
}
else
{
cin >> n >> m;
insert(n+1,m);
}
}
for (int i = r[0]; i != 1; i = r[i])
cout << e[i] << " ";
cout << endl;
return 0;
}