栈的基本操作

目录

栈的顺序存储结构及实现

栈的顺序存储结构--出栈操作       

两栈共享空间

栈的链式存储结构

栈的链式存储结构--进栈操作

出栈操作

中缀表达式转后缀表达式


栈(stack):是限定仅在表尾进行插入和删除操作的线性表

栈顶(top)==允许插入和删除的一端;

另一端的称为栈底

先进先出的线性表。LIFO结构

  • 栈的插入操作,叫做进栈、压栈或 入栈。(push)
  • 栈的删除操作,叫做出栈,也有的叫做弹栈。(pop)栈的顺序存储结构及实现

 

栈的顺序存储结构及实现

下标为0的一端作为栈底比较好

若有一个栈,StackSize是5

栈的插入,即进栈操作,其实就是做了如图所示的处理。

 

 


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

栈的顺序存储结构--出栈操作       

//若栈不空,则删除s的栈顶元素,用e返回其值,并返回OK,否则返回ERROR
Status Pop(SqStack *s,SElemType *e)
    if(s->top==-1) //栈空{
        return ERROR;
    }
    *e=S->data[s->top];  //将要删除的值赋给e
    s->top--;            //栈顶指针向下走
    return OK;
}    

两者均没有涉及到任何循环语句,时间复杂度均是O(1)。

两栈共享空间

 

栈满:S->top1+1==S->top2

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

对于两栈共享空间的push方法,我们除了要插入元素值参数外,还需要一个判断是栈1还是栈2的栈号参stackNumber。插入元素的代码如下;

/*插入元素e为新的栈顶元素*/
Status Push(SqDoubleStack *S , int e , int StackNumber)
{
    if(S->top1+1==S->top2)//栈已满,不能再push新元素了
    {
        return ERROR;
    }
    if(StackNumber==1)//栈1有元素进栈
    {
        S->data[++S->top1]=e; //若栈1则先top1+1后给数组元素赋值
    }
    if(StackNumber==2) //栈2有元素进栈
    {
        S->data[--S->top2]=e; //若栈2 则先top2后给数组元素赋值
    }
}

对于两栈共享空间的pop方法,参数就只是判断栈1栈2的参数stackNumber,代码如下;

Status Pop(SqDoubleStack *S,SElemType *e,int StackNumber)
{
    if(StackNumber==1)
    {
        if(S->top1==-1)
        {
            return ERROR;  //说明栈1已经是空栈,溢出
        }
        *e=S->data[S->top1--]; //先把删除的数据赋值,在减一
    }
    else if(StackNumber==2)
    {
        if(S->top2==MAXSIZE)
        {
            return ERROR; //说明栈2已经是空栈,溢出
        }
        *e=S->data[S->top2++] //栈2的栈顶元素
    }
    return OK;
}

栈的链式存储结构

简称链栈

空栈:top=NULL

 

栈的链式存储结构--进栈操作

进栈push操纵,假设元素为e的新结点是s,top为栈顶指针

 

/*插入元素e为新的栈顶元素*/
Status push(LinkStack *S,SElemType e)
{
    LinkStackPtr s=(linkStackPtr)malloc(sizeof(StackNode));
    s->data=e;
    s->next=S->top;  //后继链接
    S->top=s;         //改变top位置
    S->count++;
    return OK;
}

出栈操作

假设变量p用来存储要删除的栈顶结点,将栈顶指针下移一位,最后释放p即可。

 

/*若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR*/
Status Pop(LinkStack *S,SElemType *e)
{
    LinkStackPtr p;
    if(StackEmpy(S))
    {
        return ERROR;
    }
    *e=S->top->data;
    p=S->top;
    S->top=S->top->next;
    free(p); //释放
    S->count--;
    return OK;
}

链栈的进栈的push和出栈pop操作都很简单,没有任何循环操作,时间复杂度O(1)

20世纪50年代,波兰逻辑学家Jan Lukasiewicz,想到了一种不需要括号的后缀表达法,我们也把它称为逆波兰(Reverse Polish Notation,RPN)表示。这种后缀表示法,是表达式的一种新的显示方式,非常巧妙地解决了程序实现四则运算的难题。

我们先来看看,对于 "9+(3-1)*3+10/2",如果要用后缀表示法应该是什么样子:"9 3 1- 3*+ 10 2/+",这样的表达式称为后缀表达式,叫后缀的原因在于所有的符号都是在要运算数字的后面出现。

后缀表达式的计算规则:

从左到右遍历表达式的每个数字和符号,遇到是数字进栈,遇到是符号,就将处于栈顶两个数字出栈并进行运算, 运算结果进栈。

中缀表达式转后缀表达式

中缀表达式就是标准四则运算表达式。

中转后缀表达式规则:从左到右遍历中缀表达式的每个数字和符号,若是数字就是输出,即称为后缀表示式的一部分;若是符号,则判断其与栈顶符号的优先级,是右括号或优先级低于栈顶符号(乘除优先加减)则栈顶元素依次出栈,并将当前符号进栈,一直到最终输出后缀表达视为止

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值