-------------------------------------资源来源于网络,仅供自学使用,如有侵权,联系我必删.
第一:
中缀表达式符合人类的阅读和思维习惯
后缀表达式符合计算机的 “ 运算习惯”
中缀表达式 后缀表达式
5 + 3 => 5 3 +
1 + 2 * 3 => 1 2 3 * +
9 + ( 3 – 1 ) * 5 => 9 3 1 – 5 * +
第二:
将中缀表达式转换成后缀表达式 的计算方法:
? 遍历中缀表达式中的数字和符号
? 对于数字 : 直接输出
? 对于符号 :
• 左括号 : 进栈
• 符号 : 与栈顶符号进行优先级比较
• 栈顶符号优先级低 : 进栈
• 栈顶符号优先级不低 : 将栈顶符号弹出并输出 , 之后进栈
• 右括号 : 将栈顶符号弹出并输出 , 直到匹配左括号
? 遍历结束 : 将栈中的所有符号弹出并输出
第三:
算法框架
第四:
中缀表达式变后缀表达式
基于LinkList.c和LinkList.h 链表和LinkStack.c和LinkStack.h 链式栈 实现
#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;
}
第五:
计算机对后缀表达式的运算
1.解决方案
? 遍历后缀表达式中的数字和符号
? 对于数字 : 进栈
? 对于符号 :
• 从栈中弹出右操作数
• 从栈中弹出左操作数
• 根据符号进行运算
• 将运算结果压入栈中
? 遍历结束 :栈中的唯一数字为计算结果
2.算法框架
3.后缀表达式的计算
#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;
}
小结
? 中缀表达式是人习惯的表达方式
? 后缀表达式是计算机喜欢的表达方式
? 通过栈可以方便的将中缀形式变换为后缀形式
? 中缀表达式的计算过程类似程序编译运行的过程