双链表(Doubly-Linked List)
简介(Introduction)
双链表是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。
从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点
描述(Description)
- 在单链表的基础上,加入一个 \(pre\) 属性,使得其可以指向上一个元素
- 遍历方法和单链表一样,前后都可以进行遍历
- 删除:先找到待删除的节点位置,然后通过 \(pre\) 和 \(next\) 属性,进行删除
代码(Code)
-
初始化
int l[N], r[N], e[N];//左右指针和值 int cnt; void init() { // 0 表示左端点,1 表示右端点 r[0] = 1, l[1] = 0; // 左右互指 cnt = 2; // cnt 从 2 开始 }
-
在第 \(k\) 个插入的点右边插入值为 \(x\) 的点(右插)—— 传入 \(k + 1\)
void add_r(int k, int x) { e[cnt] = x; r[cnt] = r[k]; l[cnt] = k; l[r[k]] = cnt; r[k] = cnt++; // 注意:一定要先改变 r[k] 的左指针,再改变 r[k] // 一旦先改变 r[k],那么 r[k] 的左指针就失效了。 }
-
在第 \(k\) 个插入的点左边插入值为 \(x\) 的点(左插)—— 传入 \(k + 1\)
// 直接调用 add_r(l[k], x); // 第 k 个点左边插入等价于在第k个点的左边一个点的右边插入。
-
删除第 \(k\) 个插入的点——传入 \(k + 1\)
void del(int k) { r[l[k]] = r[k]; l[r[k]] = l[k]; }
应用(Application)
双链表
实现一个双链表,双链表初始为空,支持 \(5\) 种操作:
- 在最左侧插入一个数;
- 在最右侧插入一个数;
- 将第 \(k\) 个插入的数删除;
- 在第 \(k\) 个插入的数左侧插入一个数;
- 在第 \(k\) 个插入的数右侧插入一个数
现在要对该链表进行 \(M\) 次操作,进行完所有操作后,从左到右输出整个链表。
注意:题目中第 \(k\) 个插入的数并不是指当前链表的第 \(k\) 个数。例如操作过程中一共插入了 \(n\) 个数,则按照插入的时间顺序,这 \(n\) 个数依次为:第 \(1\) 个插入的数,第 \(2\) 个插入的数,…第 \(n\) 个插入的数。
输入格式
第一行包含整数 \(M\),表示操作次数。
接下来 \(M\) 行,每行包含一个操作命令,操作命令可能为以下几种:
L x
,表示在链表的最左端插入数 \(x\)。R x
,表示在链表的最右端插入数 \(x\)。D k
,表示将第 \(k\) 个插入的数删除。IL k x
,表示在第 \(k\) 个插入的数左侧插入一个数。IR k x
,表示在第 \(k\) 个插入的数右侧插入一个数。输出格式
共一行,将整个链表从左到右输出。
数据范围
\(1 \le M \le 100000\)
所有操作保证合法。
输入样例:
10
R 7
D 1
L 3
IL 2 10
D 3
IL 2 7
L 8
R 9
IL 4 7
IR 2 2
输出样例:
8 7 7 3 2 9
-
题解:
// C++ Version #include<iostream> using namespace std; const int N = 1e6 + 10; int v[N], l[N], r[N], idx; /** * 在 k 后面插入一个值为 x 的节点 * @param k 位置 * @param x 值 */ void insert(int k, int x) { v[idx] = x; r[idx] = r[k]; l[idx] = k; l[r[k]] = idx; r[k] = idx ++ ; } /** * 删除k后面一个节点 * @param k 位置 */ void del(int k) { r[l[k]] = r[k]; l[r[k]] = l[k]; } int main() { int n; cin >> n; r[0] = 1, l[1] = 0, idx = 2; while (n -- ) { string op; cin >> op; int a, b; if (op == "L") { cin >> a; insert(0, a); } else if (op == "R") { cin >> a; insert(l[1], a); } else if (op == "D") { cin >> a; del(a + 1); // idx 从 2 开始,所以下标为 a + 1 } else if (op == "IL") { cin >> a >> b; insert(l[a + 1], b); } else { cin >> a >> b; insert(a + 1, b); } } for (int i = r[0]; ~i; i = r[i]) cout << v[i] << " "; return 0; }