栈的运用与实现

栈的定义

 栈(stack)是限定在表尾进行插入和删除操作的线性表。栈又称先进后出的线性表,简称LIFO结构。

基本知识点

  1. 允许插入和删除的一端叫做栈顶,另一端叫做栈底
  2. 栈的插入操作——进栈,栈的删除操作——出栈
  3. 其特征为:1用数组存储。2只允许在一端进行插入和删除。 3先进后出(LIFO),最先进栈的必定最后出栈。类比于堆放一摞书,最先放在桌上的到后面一定被压在最下面,如果规定拿书只能从最上面拿的话,故只能最先放的书最后才能被拿到。

栈的顺序结构及实现

既然栈是线性表的特例,那么栈的顺序存储其实也是线性表顺序存储的简化,我们简称为顺序栈。
下面是栈的结构定义:

typedef int SElemType;      //根据实际情况定义,这里定义为int型
typedef struct
{
    SElemType data[MAXSIZE];  
    int top;               //用于栈顶指针
}SqStack;

以下是进栈出栈的实现:
进栈出栈的演示
进栈的操作push,代码如下:

Status Push(SqStack *S,SElemType e)  //插入
{
    if(S->top==MAXSIZE-1)
    {
        return ERROR;    //栈满
    }
    S->top++;            //栈顶指针加一
    S->data[S->top]=e;   //将新插入元素赋值给栈顶空间
    return OK;
}

栈的删除操作——出栈pop,代码如下:

Status Pop(SqStack *S,SElemType *e)   //删除
{
    if(S->top==-1)
    {
        return ERROR;    //栈空
    }
    *e=S->data[S->top];  //将要删除的栈顶元素赋值给e*
    S->top--;            //栈顶指针减一
    return OK;
}

两栈共享空间

其实栈的顺序存储是很方便的,只允许栈顶进出元素,在插入和删除时就不需要频繁移动元素了。但是它有一个很大的缺陷,就是必须设置足够大的数组空间,否则不够用了会很麻烦。为了解决这个问题,我们完全可以用一个数组才存储两个栈,就像两个人合租一个两室一厅的房子一样,可以最大化利用空间和降低租房成本。
像这样:
栈的空间共享
共享空间的思路为:数据元素在数组的两端,向中间靠拢,Ltop(top1)是栈1的栈顶指针,Rtop(top2)是栈1的栈底指针,只要它们指向的不是同一个位置,两个栈就可以一直使用。
下面代码献上:

typedef struct  //两栈共享空间结构
{
    SElemType data[MAXSIZE];
    int top1;
    int top2;
}SqDoubleStack;

Status Push(SqDoubleStack *S,SElemType e,int stackNumber)   //插入元素e为新的栈顶元素
{
    if(S->top+1==S->top2)
    {
        if(S->top1+1==top2)  //栈满,不能插入
            return ERROR;
    }
    if(stackNumber==1)
        S->data[++S->top1]=e;  //栈一进栈前+1赋值给数组元素
    else if(stackNumber==2)
        S->data[--S->top2]=e;  //栈二进栈前-1赋值给数组元素
    return OK;
}

Status Pop(SqDoubleStack *S,SElemtype *e,int stackNumber)  //删除S的栈顶元素
{
    if(stackNumber==1)
    {
        if(S->top1==-1)
            return ERROR;           //空栈,溢出
        *e=S->data[S->top1--];      //将栈1的栈顶元素出栈
    }
    else if(stackNumber==2)
    {
        if(S->top2==MAXSIZE)        //满栈,溢出
            return ERROR;
        *e=S->data[S->top2++];      //将栈1的栈顶元素出栈
    }
    return OK;
}

栈的链式存储结构及实现

栈的链式存储结构,简称为链栈。
通常对于链栈来说是不需要头结点的,像下面这张图:
链栈的存储结构
对于链栈,我们也有相应的进栈和出栈操作,快来学习一下吧!

typedef struct StackNode          //链栈的结构
{
    SElemType data;
    struct StackNode *next;
}StackNode,*LinkStackPtr;

Typedef struct LinkStack
{
    LinkStackPtr top;
    int count;
}LinkStack;

Status Push(LinkStack *S,SElemType e)   //插入e为新的栈顶元素
{
    LinkStackPtr S=(LinkStackPtr)malloc(sizeof(StackNode));
    S->data=e;
    S->next=S->top;                //把当前栈顶元素赋值给新节点的直接后继
    S->top=S;
    S->count++;
    return OK;
}

Status Pop(LinkStack *S,SElemType *e)
{
    LinkStackPtr p;
    if(StackEmpty(*S))
        return ERROR;
    *e=S->top->data;
    p=S->top;                   //栈顶元素赋值为p
    S->top=S->top->next;        //栈顶指针后移,指向后一个结点
    free(p);                    //释放空间
    S->count--;
    return OK;
}

栈的应用

栈有一个很重要的应用:在程序设计中可以实现递归的功能,例如有名的斐波那契数列的实现就可以使用栈。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值