数据-第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课-栈的应用实战二的主要内容,如果未能解决你的问题,请参考以下文章