目录
单链表
node
每个结点都包含至少两种元素:本结点的数据和下一个结点的指针。
因而该方法,各结点在逻辑上是连续的,在物理上可以不连续。
typedef struct Lnode *List;
struct Lnode{
data;
List next;
};
Lnode L;
List P;
其中P是整个链表的指针,在求表长、查找等操作时需要用到。
所以为什么不用i++?
因为各结点在物理上不连续
以求表长为例,这不是数组,没法用Lnode[i++]来遍历,但可以用指针P不断地指向当前结点的Next(也就是下一个结点的地址)来达到遍历的效果
int length(List P){
List p=P;
int j=0;
while(p){
P->Next;
j++;
}
return j;
}
在结点插入与删除时,还需要有对应的空间申请(malloc)与释放(free)操作
List p;
p=(List)malloc(sizeof(Lnode));//空间申请
free(p);//空间释放
数组模拟单链表
实现方法
用了连续的物理空间模拟链表,用数组下标关联e<结点的值>与ne<结点的next指针>,并用变量idx记录<下一次创建结点该用哪个数组下标了>
其使用的空间物理上依然是连续的,但其运行速度快,适合算法竞赛(不必考虑内存浪费)
其插入与删除操作均不需要申请、释放空间。
以其插入操作<在第k个结点后插入>为例,实质效果如下:
但实际上内存里发生的事情是:
把插入的变量放在了数组的最后,将这个数组元素(红色)的指针指向了k+1,并将k的指针指向该数(红色)
代码如下:<acwing 826.>
#include<bits/stdc++.h>
using namespace std;
const int N=100010;
int e[N],ne[N],idx=0,head=-1;
void add_to_head(int x)
{
e[idx]=x,ne[idx]=head,head=idx++;
}
void _add(int x,int k)
{
e[idx]=x,ne[idx]=ne[k],ne[k]=idx++;
}
void del(int k)
{
ne[k]=ne[ne[k]];
}
int main()
{
ios::sync_with_stdio(false);
int m,x,k;
cin>>m;
char a;
while(m--){
cin>>a;
if(a=='H'){
cin>>x;
add_to_head(x);
}
else if(a=='D'){
cin>>k;
if(!k){
head=ne[head];
}
else del(k-1);
}
else{
cin>>k>>x;
_add(x,k-1);
}
}
for(int i=head;i!=-1;i=ne[i]){
cout<<e[i]<<' ';
}
return 0;
}
链式存储(链栈)
node
其实就是个单链表,每个单位包括自身的数据< Data >与下一个结点的指针 < Next >,但插入与删除操作只能在栈顶实现
Next指向临近该元素的<靠近栈底的元素>
//Stack表示整个栈的指针,它的Next始终指向栈顶元素
typedef struct Snode *Stack;
Snode{
data;
Snode Stack;
};
操作
1.建栈(创建头结点)
Stack init()//创建头结点,返回该指针,指向整个栈的指针的Next始终指向栈顶
{
Stack S;
S=(Stack)malloc(sizeof(Snode));
return S;
}
2.检查栈是否为空
bool isempty(Stack S)
{
return S->Next==NULL;
}
3.在栈顶压入一个元素
void push(int x,Stack S)
{
Snode *p;
p=(Snode *)malloc(sizeof(Snode));
p->data=x;
p->Next=S->Next;//<新插入的元素>的Next是离它最近的<靠栈底的元素>
S->Next=p;//S的Next再次指向栈顶
}
4.删除并返回栈顶元素
int pop(Stack S)//删除并返回栈顶元素
{
Snode *fr;//后面用于释放被删除的内存
int top;//后面用于返回栈顶元素
if(isempty(S)){
cout<<"空栈"<<endl;
return NULL;
}
else {
fr=S->Next;//也就是栈顶
S->Next=fr->Next;//S的Next要一直指着栈顶,删完fr,栈顶就是fr的下一个元素
top=fr->data;
free(fr);
return top;
}
}
数组模拟栈
(acwing 828.)
//tt表示栈顶下标
#include<bits/stdc++.h>
using namespace std;
int m,tt,stk[100005];
string s;
int main()
{
ios::sync_with_stdio(false);
int x;
cin>>m;
while(m--){
cin>>s;
if(s=="push"){
cin>>x;
stk[++tt]=x;
}
else if(s=="pop"){
tt--;
}
else if(s=="empty"){
if(tt==0)cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
else{
cout<<stk[tt]<<endl;
}
}
return 0;
}