静态双链表
食用指南:
对该算法程序编写以及踩坑点很熟悉的同学可以直接跳转到代码模板查看完整代码
只有基础算法的题目会有关于该算法的原理,实现步骤,代码注意点,代码模板,代码误区的讲解
非基础算法的题目侧重题目分析,代码实现,以及必要的代码理解误区
题目描述:
-
实现一个双链表,双链表初始为空,支持 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≤M≤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 -
题目来源:https://www.acwing.com/problem/content/829/
题目分析:
- 暴力:struct数组两个指针,一个next,一个prior
- 静态:三个数组,数值域arr[],前指针域L[],后指针域r[]
头指针head,尾指针tail,节点序号idx
算法原理:
模板算法:
- 传送门:静态单链表
静态双链表:
- 双链表其实就是双向的单链表,每次操作一个方向
所以不用过度解释了吧,有问题的同学评论区留言,欢迎欢迎
1. 初始化:
const int N = 100010;
int arr[N], l[N], r[N];
int idx = 0, head = -1, tail = -1;
void init(){
r[0] = 1;
r[1] = 0;
idx = 2;
}
2. 头插:
void head_insert(int x){
arr[idx] = x;
l[idx] = -1;
r[idx] = head;
head = idx++;
}
3. 尾插:
void tail_insert(int x){
arr[idx] = x;
l[idx] = tail;
r[idx] = -1;
tail = idx++;
}
4. 指定右插:
- 向第k个插入的节点右侧插入节点:注意顺序
void r_insert(int x, int k){
arr[idx] = x;
l[idx] = k-1;
r[idx] = r[k-1];
l[r[k-1]] = idx;
r[k-1] = idx;
if(k-1 == tail){
head = idx;
}
idx++;
}
5. 指定左插:
- 向第k个插入的节点左侧插入节点:注意顺序
void l_insert(int x, int k){
arr[idx] = x;
l[idx] = l[k-1];
r[idx] = r[k-1];
r[l[k-1]] = idx;
l[k-1] = idx;
if(k-1 == head){
head = idx;
}
idx++;
}
6. 删除:
- 删除第k个插入节点的后一个节点:
还是分两部分:尾巴 & 非尾巴
void r_remove(int k){
if(r[k-1] == tail){
//第k个插入的节点后是尾节点
tail = k-1;
}else{
//顺序不可颠倒
l[r[[r[k-1]]]] = k-1;
r[k-1] = r[r[k-1]];
}
}
- 删除第k个插入节点的前一个节点:
还是分两部分:删头 & 非头
void l_remove(int k){
if(l[k-1] == head){
head = k-1;
}else{
r[l[l[k-1]]] = k-1;
l[k-1] = l[l[k-1]];
}
}
####7. 遍历:
- 从前向后:
int t = head;
while(t != -1){
cout<<arr[t]<<" ";
t = r[t];
}
- 从后向前:
int t = tail;
while(t != -1){
cout <<arr[t]<<" ";
t = l[t];
}
代码误区:
1. 删除节点的分情况讨论:
- 删除第k个插入节点的前一个节点:前一个是头节点 / 普通节点
- 删除第k个插入节点的后一个节点:后一个是尾节点 / 普通节点
2. 删除的顺序:
- 顺序不可以颠倒:先连接,后断开。
本篇感想:
- 学会静态单链表之后,静态双链表应该很容易掌握,毕竟就算是双链表,每次操作的时候也只针对一个方向
- 静态链表篇结束,按理说应该是栈 & 队列,但是我迫不及待手撸哈希了,下一篇写拉链哈希,别慌,静态链表够用了
- 看完本篇博客,恭喜已登《练气境-初期》
距离登仙境不远了,加油