链表
我看了下其他人的wp,单链表维护一个呀把头节点会更好,双链表就是两个头尾。
单链表
这道题目做到吐血。一定要做好注释,不要把1和0都写不对。
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int main()
{
int m;
int p;
int v;
int time=1;
int idx;
int workp=0;
int head = 0;
cin >> m;
char opt;
int K[100100]={0};
int P[100100]={0};
int V[100100]={0};
int freeidx=1;//低级错误了,把0当成freeidx的开头了,现在好了
//设置表头
P[0] = -1; //0号位置是表头
V[0] = 0; //0号位置的值是0
while (m -- ){
cin >> opt;
if(opt=='H'){//在表头插入的意思是放在第一个,哎,不是在第一个后面插入,又看错了
idx = freeidx++;
cin >> v;
P[idx] = P[0];
V[idx] = v;
P[0] = idx;
K[time++] = idx;//记录对应次数和索引
}else if(opt == 'D'){//注意是删除第k个数的后面的数不是第k个数。。无语了
cin >> v;
if(v==0){
workp = P[head];
P[head] = P[workp];
P[workp] = 0;
V[workp] = 0;
continue;
}//如果是0直接处理头
//获取第k个插入的数的索引
v = K[v];
workp = P[v];
//存储上一个头,把上一个头的下一个指针,指向workp的指针
P[v] = P[workp];
P[workp] = 0;
V[workp] = 0;
}else if(opt =='I'){
int k;
cin >> k >> v;
workp = K[k];
idx = freeidx++;
P[idx] = P[workp];
V[idx] = v;
P[workp] = idx;
K[time++] = idx;
}
}
workp = P[head];
while(workp!=-1){
cout<<V[workp]<<" ";
workp = P[workp];
}
return 0;
}
双链表
可写死我了,要注意不同的情况。打pwn做这种太ez
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
struct link{
int l;
int r;
int v;
};
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int times=1;
int freeidx=0;
int leftL = -2;
int rightL = -2;
int m;
int v;
int k;
string opt;
int workp = 0;
cin >> m;
vector<int> K(m+10,0);
vector<link> L(m+10);//三位分别是左指针,右指针,值
for (int i = 0; i < m; i ++ ){
L[i].l=-2;L[i].r=-2;L[i].v=0;//-2是没有,-1是结束。
}
//注意被处理的块是在中间、两边、单独的情况
while(m--){
cin >> opt;
if(opt=="L"){
cin >> v;
if(leftL==-2){//不存在最左边堆块,说明空链表,直接插入
L[freeidx].l = -1;
L[freeidx].r = -1;
L[freeidx].v = v;
leftL = freeidx;
rightL = freeidx;
K[times++] = freeidx++;
continue;
}
//如果有直接在最左边插入
L[freeidx].l=-1;
L[freeidx].r = leftL;
L[freeidx].v = v;
L[leftL].l = freeidx;
leftL = freeidx;
K[times++] = freeidx++;
}else if(opt=="R"){
cin >> v;
if(rightL==-2){
L[freeidx].l=-1;
L[freeidx].r=-1;
L[freeidx].v=v;
leftL = freeidx;
rightL = freeidx;
K[times++] = freeidx++;
continue;
}
L[freeidx].r = -1;
L[freeidx].l = rightL;
L[freeidx].v = v;
L[rightL].r = freeidx;
rightL = freeidx;
K[times++] = freeidx++;
}else if(opt=="D"){
cin >> v;
workp = K[v];//获得当前索引
if(leftL==workp&&rightL==workp){
//只有我一个啊
leftL = -2;
rightL = -2;
continue;
}
if(L[workp].l==-1){
leftL = L[workp].r;
L[L[workp].r].l = -1;//下一个的上一个变成他的上一个
continue;
}
if(L[workp].r==-1){
rightL = L[workp].l;
L[L[workp].l].r = -1;//上一个堆块的下一个堆块变成他的下一个
continue;
}
L[L[workp].l].r = L[workp].r;//上一个堆块的下一个堆块变成他的下一个
L[L[workp].r].l = L[workp].l;//下一个的上一个变成他的上一个
}else if(opt=="IL"){
cin >> k >> v;
//在K[k]的左边加上v
workp = K[k];
L[freeidx].r = workp;
L[freeidx].l = L[workp].l;//新的块的左右指向对应的地方
L[freeidx].v = v;
L[workp].l = freeidx;//更新其下一个指向他
if(L[freeidx].l==-1){
leftL = freeidx;
}else{
L[L[freeidx].l].r = freeidx;//更新其上一个指向他
}
K[times++] = freeidx++;
}else if(opt=="IR"){
cin >> k >> v;
//在K[k]的有右边加上v
workp = K[k];
L[freeidx].l = workp;
L[freeidx].r = L[workp].r;//新的块的左右指向对应的地方
L[freeidx].v = v;
L[workp].r = freeidx;//更新其下一个指向他
if(L[freeidx].r==-1){
rightL = freeidx;
}else{
L[L[freeidx].r].l = freeidx;//更新其上一个指向他
}
K[times++] = freeidx++;
}
}
workp = leftL;
while(workp!=-1&&workp!=-2){
cout << L[workp].v << " ";
workp = L[workp].r;
}
return 0;
}