数据-第16课-栈的应用实战二

Posted free-1122

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据-第16课-栈的应用实战二相关的知识,希望对你有一定的参考价值。

第16课-栈的应用实战二

 

1. 问题的提出

计算机的本质工作就是数学运算,那计算机可以读入字符串”9 + (3 - 1) *5 +8/2”并且计算值吗?

 

2. 后缀表达式

波兰科学家在20世纪50年代提出了一种将运算符放在数字后面的后缀表达式。

对应的,我们平时用的数学表达式叫做中缀表达式。

实例

5 + 3 => 5 3 +

1 + 2 * 3 => 1 2 3 * +

9 + ( 3–1 ) * 5 => 9 3 1–5 * +

中缀表达式符合人类的阅读和思维习惯;后缀表达式符合计算机的“运算习惯”。

 

3. 解决方案

遍历中缀表达式中的数字和符号。

对于数字:直接输出 。

对于符号:

左括号:进栈

符号:与栈顶符号进行优先级比较,栈顶符号优先级低:进栈

栈顶符号优先级不低:将栈顶符号弹出并输出,之后进栈 ,之后进栈

右括号:将栈顶符号弹出并输出,直到匹配左括号

遍历结束:将栈中的所有符号弹出并输出。

 

4. 整体框架

transform(exp)

         创建栈 s;

         i = 0;

        

         while(exp[i] != ‘\0‘)

        

                  if(exp[i]为数字)

                 

                           Output(exp[i]);         

                 

                  else if(exp[i]为符号)

                 

                           while(exp[i]优先级 <= 栈顶符号优先级)

                          

                                    output(栈顶优先级);

                                    Pop(S);     

                          

                           Push(S,exp[i]); 

                 

                  else if(exp[i]为右括号)

                 

                           while(栈顶符号不为括号)

                          

                                    output(栈顶符号);

                                    Pop(S);     

                                  

                 

                  从S中弹出左括号;

                  else

                 

                           报错,停止循环;        

                 

                  i++;        

        

         while((Size(S) > 0)&&(exp[i]==‘\0‘))

        

                  output(栈顶符号);

                  Pop(S);     

        

 

5. 中缀转后缀的算法

#include <stdio.h>

#include "LinkStack.h"

 

int isNumber(char c)

    return (‘0‘ <= c) && (c <= ‘9‘);

 

int isOperator(char c)

    return (c == ‘+‘) || (c == ‘-‘) || (c == ‘*‘) || (c == ‘/‘);

 

int isLeft(char c)

    return (c == ‘(‘);

 

int isRight(char c)

    return (c == ‘)‘);

 

int priority(char c)

    int ret = 0;

   

    if( (c == ‘+‘) || (c == ‘-‘) )

   

        ret = 1;

   

   

    if( (c == ‘*‘) || (c == ‘/‘) )

   

        ret = 2;

   

   

    return ret;

 

void output(char c)

    if( c != ‘\0‘ )

   

        printf("%c", c);

   

 

void transform(const char* exp)

    LinkStack* stack = LinkStack_Create();

    int i = 0;

   

    while( exp[i] != ‘\0‘ )

   

        if( isNumber(exp[i]) )

       

            output(exp[i]);

       

        else if( isOperator(exp[i]) )

       

            while( priority(exp[i]) <= priority((char)(int)LinkStack_Top(stack)) )

           

                output((char)(int)LinkStack_Pop(stack));

           

           

            LinkStack_Push(stack, (void*)(int)exp[i]);

       

        else if( isLeft(exp[i]) )

       

            LinkStack_Push(stack, (void*)(int)exp[i]);

        

        else if( isRight(exp[i]) )

       

            char c = ‘\0‘;

           

            while( !isLeft((char)(int)LinkStack_Top(stack)) )

           

                output((char)(int)LinkStack_Pop(stack));

           

           

            LinkStack_Pop(stack);

       

        else

       

            printf("Invalid expression!");

            break;

       

       

        i++;

   

   

    while( (LinkStack_Size(stack) > 0) && (exp[i] == ‘\0‘) )

   

        output((char)(int)LinkStack_Pop(stack));

   

   

    LinkStack_Destroy(stack);

int main()

    transform("9+(3-1)*5+8/2");

   

    printf("\n");

   

    return 0;

6. 计算机的计算习惯

计算机对后缀表达式的运算是基于栈的

解决方案:

遍历后缀表达式中的数字和符号

对于数字:进栈

对于符号:

从栈中弹出右操作数

从栈中弹出左操作数

根据符号进行运算

将运算结果压入栈中

便利结束:栈中的唯一数字为计算结果

 

7. 算法框架

compute(exp)

         创建栈 S;

         i = 0;

        

         while(exp[i] != ‘\0‘)

        

                  if(exp[i] 为数字)

                 

                           Push(S,exp[i]); 

                         

                  else if(exp[i]为符号)

                 

                           1、丛栈中弹出右操作数;

                           2、从栈中弹出左操作数;

                           3、根据符号进行运算;

                           4、Push(stack,结果);     

                 

                  else

                 

                           报错,停止循环;        

                 

                  i++;

        

         if((Size(S) == 1) && (exp[i] == ‘\0‘))

        

                  栈中唯一的数字为运算结果;    

        

         返回结果;           

程序:

#include <stdio.h>

#include "LinkStack.h"

 

int isNumber(char c)

    return (‘0‘ <= c) && (c <= ‘9‘);

 

int isOperator(char c)

    return (c == ‘+‘) || (c == ‘-‘) || (c == ‘*‘) || (c == ‘/‘);

 

int value(char c)

    return (c - ‘0‘);

 

int express(int left, int right, char op)

    int ret = 0;

   

    switch(op)

   

        case ‘+‘:

            ret = left + right;

            break;

        case ‘-‘:

            ret = left - right;

            break;

        case ‘*‘:

            ret = left * right;

            break;

        case ‘/‘:

            ret = left / right;

            break;

        default:

            break;

   

   

    return ret;

 

int compute(const char* exp)

    LinkStack* stack = LinkStack_Create();

    int ret = 0;

    int i = 0;

   

    while( exp[i] != ‘\0‘ )

   

        if( isNumber(exp[i]) )

       

            LinkStack_Push(stack, (void*)value(exp[i]));

       

        else if( isOperator(exp[i]) )

       

            int right = (int)LinkStack_Pop(stack);

            int left = (int)LinkStack_Pop(stack);

            int result = express(left, right, exp[i]);

           

            LinkStack_Push(stack, (void*)result);

       

        else

       

            printf("Invalid expression!");

            break;

       

       

        i++;

   

   

    if( (LinkStack_Size(stack) == 1) && (exp[i] == ‘\0‘) )

   

        ret = (int)LinkStack_Pop(stack);

    

    else

   

        printf("Invalid expression!");

   

   

    LinkStack_Destroy(stack);

   

    return ret;

 

int main()

    printf("9 + (3 - 1) * 5 + 8 / 2 = %d\n", compute("931-5*+82/+"));

   

    return 0;

 

小结:

中缀表达式是人习惯的表达方式。

后缀表达式是计算机喜欢的表达方式。

通过栈可以方便的将中缀形式变换为后缀形式。

中缀表达式的计算过程类似程序编译运行的过程。

以上是关于数据-第16课-栈的应用实战二的主要内容,如果未能解决你的问题,请参考以下文章

栈的实现

栈的应用(括号匹配算法实战)

第34课 栈的概念及实现(上)

《前端serverless 面向全栈的无服务器架构实战》读书笔记

实战说明TCP协议栈的数据包拆包粘包问题

数据结构与算法目录