链表:通过索引寻找下一个节点的数据结构,每个节点包含当前数据和寻找到下一个数据的索引。
相比于结构体模拟链表,用数组模拟链表的代码相对简洁。
大体思路:
单链表 :两个数组,一个数组存数据,一个数组存下一个节点的下标,用idx控制开辟新的空间。双链表:三个数组,一个数组存数据,一个数组存左节点,一个数组存右节点,初端末端用特殊指向表示。
单链表
#include<iostream>
using namespace std;
const int N=100010;
//inx表示存储用到了哪个点
int head,e[N],ne[N],idx;
//初始化
void init()
{
head=-1;
idx = 0;
}
//将x插入头结点
void add_to_head(int x)
{
ne[idx] = head;
e[idx]=x;
head = idx;
idx++;//注意头结点增加时也要idx++
}
//插入操作
void add(int k,int x)
{
e[idx]=x;
ne[idx] = ne[k];
ne[k]=idx;
//en[k]指向插入的节点
//插入的节点指向en[k]原来指向的节点
idx++;
}
//将下标k的后面的点删掉
void remove(int k)
{
ne[k]=ne[ne[k]];
//k这个位置的节点指向 (k指向的)下一个节点 指向的节点
}
int main()
{
int M;
cin>>M;
init();
while(M--)
{
int x,k;
char ch;
cin>>ch;
if(ch=='H')
{
cin>>x;
add_to_head(x);
}
else if(ch=='D')
{
cin>>k;
if(!k)
head=ne[head];
else remove(k-1);//下标为从零开始,故-1操作
}
else if(ch=='I')
{
cin>>k>>x;
add(k-1,x);
}
}
for(int i=head;i!=-1;i=ne[i])
cout<<e[i]<<' ';
cout<<endl;
return 0;
}
双链表
注意画图理解链表的指向问题
#include<iostream>
using namespace std;
const int N=100010;
int r[N],l[N],e[N],idx;
void init(){
r[0]=1;
l[1]=0;
idx=2;
}
void add(int k,int x)
{
e[idx]=x;
r[idx]=r[k];
l[idx]=k;
l[r[k]]=idx;
r[k]=idx++;
}
void remove(int k)
{
l[r[k]]=l[k];
r[l[k]]=r[k];
//左侧的右侧等于右侧,右侧的左侧等于左侧
}
int main()
{
int n;
cin>>n;
init();
while(n--)
{
string ch;
int k,x;
cin>>ch;
if(ch=="L")
{
cin>>x;
add(0,x);
}
else if(ch=="R")
{
cin>>x;
add(l[1],x);
}
else if(ch=="D")
{
cin>>k;
remove(k+1);
}
else if(ch=="IR")
{
cin>>k>>x;
add(k+1,x);
}
else if(ch=="IL")
{
cin>>k>>x;3
add(l[k+1],x);
}
}
int p=r[0];
while(p!=1)//指向1就是右侧终点
{
cout<<e[p]<<' ';
p=r[p];
}
cout<<endl;
}