单链表、链栈及其数组模拟

目录

单链表

node

数组模拟单链表

实现方法

链式存储(链栈)

node

操作

数组模拟栈


单链表

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;
}

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_Wyatt

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值