【数据结构实验】栈的应用

实验三 栈的应用

1.实验目的:

熟悉栈的定义,栈的特点以及栈的基本操作。能够根据实际情况选择合适的存储结构,解决实际问题。

2.实验内容:

对任意给定的一个中缀算术表达式,输出等价的后缀形式。

3.正文部分

①什么是栈

栈也称为堆栈,是一种先进后出,删除和插入都在栈顶操作的线性表。

特性:先进后出,后进先出。

最先放入栈的最后被拿出来,最后放入栈的内容最先被拿出来。

栈的插入

push():在栈顶插入元素

image-20220415000023947

栈的删除

push():在栈顶移除一个元素,并将栈数-1

image-20220415000853073

②栈的基本操作
InitStack(&S) 操作结果:构造一个空栈S。

首先分配好一些内存,之后让栈顶等于栈底(栈内无任何元素)

void Init(SqStack s)
{
    s.base=(int *)malloc(size*sizeof(int));
    s.top=s.base;
    s.stacksize=size;
}
Push(&S,e) 操作结果:插入元素e为新的栈顶元素

初始条件:栈S已存在

向栈顶申请内存+1,再让栈顶元素成为e

void push(SqStack s,int e)
{
    if(s.top-s.base>s.stacksize)//如果栈内元素未满
    {
       s.base=(int *)realloc(s.base,(s.stacksize+incresize)*sizeof(int));
    s.top=s.base+s.stacksize;
    s.stacksize+=incresize; 
    }
    *s.top++=e;
}
Pop(&S, &e) 操作结果:删除S的栈顶元素,并用e返回其值

初始条件:栈S已存在且非空

栈顶元素-1

void pop(SqStack s,int e)
{
    if(s.top!=s.base)
    {
        e=*(--s.top);
    }
    cout<<e<<endl;
}
打印函数

输出所有数组

void Print(SqStack *s)
{
    int *temp;
    temp =s->top;//top
    while(temp!=s->base)
    {
        temp--;
        printf("%d",*temp);
    }
}
③栈的应用——数制转换

算法原理:N=(N div d)×d+N mod d

例:十进制转八进制

十进制1348转八进制2504

NN div 8N mod
13481684
168210
2125
202

计算顺序由上至下 输出顺序由下至上

void conversion()
{
InitStack(S);
scanf("%d",N);
while(N){
    Push(S,N%8);
    N=N/8;
}
    while(!StackEmpty(S)){
        Pop(S,e);
        printf("%d",e);
    }
}
④栈的应用——括号匹配的检验

检验括号是否匹配的方法:可用“期待的急迫程度”这个概念来描述。

[ ( [ ] [ ] ) ]
1 2 3 4 5 6 7 8

1对应8 2对应7 3对应4 5对应6

出现不匹配的三种可能情况:

1.到来的右括弧不是所“期待”的;

2.到来的是“不速之客”

3.直到结束,也没有到来所期待的括弧;

  • 凡出现左括弧,则进栈;

  • 凡出现右括弧,首先检查栈是否为空

    若栈空,则表明“右括弧”多余

    否则和栈顶元素比较

    若相匹配,则“左括弧出栈”

    否则表明不匹配;

  • 表达式检验结束时,若栈空,则表明表达式中匹配正确,

    否则表明“左括弧”有余;

⑤栈的应用——表达式求值

表达式的三种标识方法:

Exp = S1 + OP + S2(操作数1 + 操作符 + 操作数2)

前缀表示法:OP + S1 + S2

中缀表示法:S1 + OP + S2

后缀表示法:S1 + S2 + OP

大众使用的通常是中缀表示法。

例:

Exp=a × b + (c - d / e) × f

前缀式: + × a b × -c/d e f

中缀式: a × b + c - d / e × f

后缀式: a b × c d e / - f × +

  • 后缀式求值:先找运算符,再找操作数。

    一般找到运算符后对应的前面两个(未被处理过的)就是该操作符的对应操作数,如果前面含有已经处理过的操作数,那就把处理过后的两个操作数看成一个,往前数两个就是了。

⑥栈的应用——栈的递归调用

递归函数:一个直接调用自己或通过一系列的调用语句间接地调用自己的函数。

#include<stdio.h>
int f(int m)
{
    if(m==1)
         return 1;
    else
    {
        printf("m=%d\n",m);
        return f(m-1);
    }
}
int main()
{
    int n;
    int f(int m);
    printf("请输入一个大于1的数");
    scanf("%d",&n);
    printf("%d\n",f(n));
    return 0;
}
⑦栈的实现
  • 顺序栈:指向表尾的指针可以作为栈顶指针

    #define STACK_INIT_SIZE 100
    typedef struct{
        SElemType *base;
        SElemType *top;
        int stacksize;
    }SqStack;
    

构造一个最大空间为maxsize的空顺序栈S:

Status InitStack (SqStack &S,int maxsize)
{
    S.base=new ElemType[maxsize];
    if(!S.base) exit (OVERFLOW);//存储分配失败
    S.top = S.base;
    S.stacksize=maxsize;
    return OK;
}
  • 链栈

    线性表有顺序存储结构和链式存储结构,栈属于线性表的一种,也具有顺序存储结构和链式存储结构

⑧中缀表达式转后缀表达式

(a+b)→(ab+)

中缀表达式运算规则:优先级高的先算,相同优先级的运算符顺序是从左往右。

后缀表达式特点:数字的顺序与中缀一样,运算顺序根据从左到右遇到运算符的顺序进行。(出现的顺序)

转换核心思想:比较相邻的两个运算符,优先级高的先算

注意要点:

1.数字可能是多位数,也可能是小数;

2.数字前面可能有正号或者负号


完整源码下载:数据结构——栈的应用

  • 9
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

AKA山风点火

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

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

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

打赏作者

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

抵扣说明:

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

余额充值