【定义】
链表是一种物理存储单元上非连续、非顺序的存储结构。数据元素的逻辑顺序是通过链表中的指针链接次序实现的。
链式存储结构的特点是用一组任意的存储单元来存储线性表中的数据元素。这样在插入和删除元素时,可以通过直接修改指针完成操作,时间效率大大提高。但因为链式存储结构的存储单元不连续,所以需要通过指针来访问它的后续元素。
为了表示每个数据元素与其直接后继数据元素之间的逻辑关系,我们需要存出一个其直接后继的存储位置。我们把存储数据元素信息的域成为数据域,把存储后继位置的域称为指针域,这两部分构成一个节点。
一.单链表
【定义】
n个节点链接成一个链表,即为线性表的链式存储结构。因为每个节点只有一个指针域,所以又将这样的链表称为单链表。
【分析】
1.初始状态,head节点指向空集(即-1),为的就是在后面进行不断操作后仍然可以知道链表是在什么时候结束;
2.idx在一开始的时候,作为链表的下标,便于寻找;在链表进行各种插入、删除等操作时,作为一个临时的辅助性的所要操作的元素的下标来帮助操作。
(1)插入
a.在头指针插入一个元素x
先将x放进去,再让x的指针指向head原本指向的(即把x插到head后面),然后令头结点指向该元素T_T(head=idx),idx 指向下一个可存储元素的位置 (idx++)。
b.在k后面插入一个元素x
先将元素x放进去,让x对应的next指针指向要插入位置的下一个数,再让原来元素的指针指向自己,idx向后挪。
(2)删除
让k的指针指向k的下一个的下一个,这样中间那个就要say byebye啦
【代码】
#include <bits/stdc++.h>
using namespace std;
const int N=100010;
int ne[N],e[N],head,idx;
int m;
void init(){
head=-1;
idx=0;
}//初始化
void add_to_head(int x){
e[idx]=x;
ne[idx]=head;
head=idx++;
}//在头结点插入x
void add(int k,int x){
e[idx]=x;
ne[idx]=ne[k];
ne[k]=idx++;
}//在k的下一个数插入x
void remove(int k){
ne[k]=ne[ne[k]];
}//删除k的下一个数
int main(){
cin>>m;
init();
while(m--){
int k,x;
char op;
cin>>op;
if(op=='H'){
cin>>x;
add_to_head(x);
}
else if(op=='I'){
cin>>k>>x;
add(k-1,x);
}
else{
cin>>k;
if(k==0) head=ne[head];//特判
else remove(k-1);
}
}
for(int i=head;i!=-1;i=ne[i]){
cout<<e[i]<<" ";
}
return 0;
}
二.双链表
【定义】
双向链表即单链表由单向的链变成了双向的链(一个指针域(next)变成一前一后两个指针域(prev,next))
【分析】
1.开三个数组
(1) e[]用来存储数值
(2) l[]用来存储前驱(左边数的下标)
(3) r[]用来存储后继(右边数的下标)
2.索引为k(第k个插入的数,不是指当前序列的第k个数),则对第k-1个数进行操作,相应的,在主函数中调用时使用索引应该为k+1
(1) 插入
放入新元素x,将新节点分别指向插入位置的右节点和左节点,再将新节点右边的向左指向新节点,将新节点左边的向右指向新节点,最后idx++ ~
(2) 删除
删除第k个插入的数,第k-1的右指针指向原先第k个节点的右指针指向的节点,删除第k个节点,原先第k个节点的右指针指向的节点的左指针指向原先第k个节点的左指针指向的节点
遍历的出口为 i!=1,因为 1 代表着尾节点。
【代码】
#include <bits/stdc++.h>
using namespace std;
const int N=100010;
int e[N],l[N],r[N],idx;
void init(){
l[1]=0,r[0]=1;
idx=2;
}//这里的初始化导致了操作元素的索引为k+1
void add(int k,int x){
e[idx]=x;
r[idx]=r[k];
l[idx]=k;
l[r[k]]=idx;
r[k]=idx++;
}//在k的右边插入一个数x
void remove(int k){
r[l[k]]=r[k];
l[r[k]]=l[k];
}//删除第k个插入的数
int main(){
int m;
cin>>m;
init();
while(m--){
int k,x;
string op;
cin>>op;
if(op=="L"){
cin>>x;
add(0,x);
}
else if(op=="R"){
cin>>x;
add(l[1],x);
}
else if(op=="D"){
cin>>k;
remove(k+1);
}
else if(op=="IL"){
cin>>k>>x;
add(l[k+1],x);
}
else {
cin>>k>>x;
add(k+1,x);
}
}
for(int i=r[0];i!=1;i=r[i]){
cout<<e[i]<<" ";
}
return 0;
}