栈的应用:中缀表达式转后缀表达式
计算机的本质工作就是做数学运算,那计算机可以读入字符串
“9 + (3 - 1) * 5 + 8 / 2”并计算值吗?
后缀表达式 ==?符合计算机运算
波兰科学家在20世纪50年代提出了一种将运算符放在数字后面的后缀表达式对应的,
我们习惯的数学表达式叫做中缀表达式===》符合人类思考习惯
实例:
5 + 4=> 5 4 +
1 + 2 * 3 => 1 2 3 * +
8 + ( 3 – 1 ) * 5 => 8 3 1 – 5 * +
中缀表达式符合人类的阅读和思维习惯
后缀表达式符合计算机的“运算习惯”
如何将中缀表达式转换成后缀表达式?
中缀转后缀算法:
遍历中缀表达式中的数字和符号
1.对于数字:直接输出
2.对于符号:
左括号:入栈(左括号优先级最低)
运算符:与栈顶符号进行优先级比较
若栈顶符号优先级低:入栈
若栈顶符号优先级不低:将栈顶符号弹并输出,之后进入栈
右括号:将栈顶符号弹出并输出,直到匹配左括号
3.遍历结束:将栈中所有符号弹出并输出
计算机是如何基于后缀表达式计算的?
8 3 1 – 5 * +
遍历后缀表达式中的数字和符号
1.对于数字:进栈
2.对于符号:
从栈中弹出右操作数
从栈中弹出左操作数
3.根据符号进行运算
4.将运算结果压入栈中
计算机的本质工作就是做数学运算,那计算机可以读入字符串
“9 + (3 - 1) * 5 + 8 / 2”并计算值吗?
后缀表达式 ==?符合计算机运算
波兰科学家在20世纪50年代提出了一种将运算符放在数字后面的后缀表达式对应的,
我们习惯的数学表达式叫做中缀表达式===》符合人类思考习惯
实例:
5 + 4=> 5 4 +
1 + 2 * 3 => 1 2 3 * +
8 + ( 3 – 1 ) * 5 => 8 3 1 – 5 * +
中缀表达式符合人类的阅读和思维习惯
后缀表达式符合计算机的“运算习惯”
如何将中缀表达式转换成后缀表达式?
中缀转后缀算法:
遍历中缀表达式中的数字和符号
1.对于数字:直接输出
2.对于符号:
左括号:入栈(左括号优先级最低)
运算符:与栈顶符号进行优先级比较
若栈顶符号优先级低:入栈
若栈顶符号优先级不低:将栈顶符号弹并输出,之后进入栈
右括号:将栈顶符号弹出并输出,直到匹配左括号
3.遍历结束:将栈中所有符号弹出并输出
计算机是如何基于后缀表达式计算的?
8 3 1 – 5 * +
遍历后缀表达式中的数字和符号
1.对于数字:进栈
2.对于符号:
从栈中弹出右操作数
从栈中弹出左操作数
3.根据符号进行运算
4.将运算结果压入栈中
5.遍历结束:栈中的唯一数字为计算结果
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include<stdio.h>
#include <string.h>
#include "linkstack.h"
#include "linklist.h"
int i=0;//全局变量记录次数
//判断是否为操作符
int isOper(char c)
{
int ret = 0;
if ((c== '+')||(c== '-')||(c== '*')||(c== '/'))
{
ret = 1;
return ret ;
}
return 0;
}
//判断是否为数
int isNum(char c)
{
return ('0'<=c)&&(c<='9');
}
//计算
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;
default:
break;
}
return ret ;
}
//判断操作符的优先级
int priority(char c)
{
int ret = 0;
if ((c=='+')||(c=='-'))
{
ret = 1;
}
if ((c=='*')||(c=='/'))
{
ret = 2;
}
return ret;
}
//通过二级指针改变一级指针的值
//保存转换后的 后缀表达式字符串
void output(char c,char **p)
{
if (c!='\0')
{
printf("%c",c);
(*p)[i++]=c;
}
(*p)[i] = '\0';
}
//判断(
int isLeft(char c)
{
int ret =0;
if (c=='(')
{
ret = 1;
return ret;
}
return ret;
}
//判断)
int isRight(char c)
{
int ret =0;
if (c==')')
{
ret = 1;
return ret;
}
return ret;
}
//将字符转为对应的int数字
int value(char c)
{
return (c-'0');
}
//扫描 中缀转后缀算法
/************************************************************************/
/* 1.对于数字:直接输出
2.对于符号:
左括号:入栈(左括号优先级最低)
运算符:与栈顶符号进行优先级比较
若栈顶符号优先级低:入栈
若栈顶符号优先级不低:将栈顶符号弹并输出,之后进入栈
右括号:将栈顶符号弹出并输出,直到匹配左括号
3.遍历结束:将栈中所有符号弹出并输出
char **p;通过二级指针做函数参数 改变一级指针的值
/************************************************************************/
void scanner(const char *code,char **p)
{
int i = 0,ret = 0;
LinkStack*stack = NULL;
stack = LinkStack_Create();
if (stack ==NULL)
{
ret = -1;
printf("stack == null %d\n",ret);
return;
}
//扫描字符串
while (code[i]!='\0')
{
if (isNum(code[i]))
{
output(code[i],p);
}
else if(isOper(code[i]))
{
while (priority(code[i])<=priority((char)(int)LinkStack_Top(stack)))
{
output((char)(int)LinkStack_Pop(stack),p);
}
LinkStack_Push(stack,(void*)(int)code[i]);
}
else if(isLeft(code[i]))
{
LinkStack_Push(stack,(void*)(int)code[i]);
}
else if(isRight(code[i]))
{
while (!isLeft((char)(int)LinkStack_Top(stack)))
{
output((char)(int)LinkStack_Pop(stack),p);
}
//弹出左括号
LinkStack_Pop(stack);
}
else
{
printf("Invalid code\n");
break;
}
i++;
}
//遍历结束 将栈中所有符号弹出
while((LinkStack_Size(stack)>0)&&(code[i]=='\0'))
{
output((char)(int)LinkStack_Pop(stack),p);
}
LinkStack_Destroy(stack);
}
/************************************************************************/
//计算机 根据后缀表达式进行计算 返回计算结果
/* 计算机是如何基于后缀表达式计算的?
遍历后缀表达式中的数字和符号
1.对于数字:进栈
2.对于符号:
从栈中弹出右操作数
从栈中弹出左操作数
3.根据符号进行运算
4.将运算结果压入栈中
5.遍历结束:栈中的唯一数字为计算结果 */
/************************************************************************/
int compute(const char *exp)
{
int i = 0,ret = -1;
LinkStack*stack = NULL;
stack = LinkStack_Create();
if (stack ==NULL)
{
ret = -1;
printf("stack == null %d\n",ret);
return ret;
}
//扫描后缀表达式
while (exp[i]!='\0')
{
if (isNum(exp[i]))
{
LinkStack_Push(stack,(void*)value(exp[i]));
}
else if (isOper(exp[i]))
{
int right = (int)LinkStack_Pop(stack);
int left = (int)LinkStack_Pop(stack);
int num = express(left,right,exp[i]);
printf("num:%d\n",num);
LinkStack_Push(stack,(void*)num);
}
else
{
printf("invalid express\n");
break;
}
//printf("i:%d\n",i);
i++;
}
//遍历结束 将栈中所有符号弹出
while((LinkStack_Size(stack)>0)&&(exp[i]=='\0'))
{
ret = (int)LinkStack_Pop(stack);
}
LinkStack_Destroy(stack);
return ret;
}
int main()
{
char *a;
int num ;
//目前只支持个位数字 10+ 出错
const char *code = "8+(3-1)*5";
a = (char*)malloc(100*sizeof(a));
//指针做输入 主调函数分配内存
scanner(code,&a);
printf("\n%s\n",a);
num = compute(a);
printf("num:%d\n",num);
free(a);
system("pause");
return 0;
}