中缀转后缀算法
对于数字:直接输出
对于符号:
- 左括号:进栈
- 运算符号:与栈顶符号优先级比较
- 若栈顶符号优先级低,符号进栈(默认栈顶若是左括号 左括号优先级最低)
- 若栈顶优先级不低,将栈顶符号弹出,之后进栈
- 右括号:将栈顶符号弹出并输出,直到匹配到左括号
遍历结束:栈中所有符号弹出并输出
计算后缀表达式算法
遍历表达式的数字和符号
对于数字:进栈
对于符号:
- 从栈中弹出右操作数
- 从栈中弹出左操作符
- 根据符号运算
- 把运算结果压入栈中
遍历结束:栈中唯一数字为操作结果
代码
//
// Created by xuehu96 on 2019-08-14.
//
#include <stdio.h>
#include <string.h>
#include "../linkstack.h"
int myStr2Int(const char *str);
int isLeft(const char c);
int isRight(const char c);
/*
int static isLeft(const char c)
{
return (c == '(');
}
int static isRight(const char c)
{
return (c == ')');
}*/
int isOperator(const char c)
{
return (c == '+') || (c == '-') || (c == '*') || (c == '/');
}
int isNumber(const char c)
{
return ('0' <= c) && (c <= '9');
}
int priority(const char c) //优先级判断
{
int ret = 0;
if((c == '+') || (c == '-'))
{
ret = 1;
}
if((c == '*') || (c == '/'))
{
ret = 2;
}
return ret;
}
int express(int left, int right, const 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;
}
return ret;
}
char *transform(const char *zzexpr, char *hzexpr) //后缀表达式转中缀表达式
{
int i = 0, j = 0;
LinkStack *list = LinkStack_Create ();
if(list == NULL)
{
printf ("LinkStack_Create()error\n");
return NULL;
}
while(zzexpr[i] != '\0') //遍历字符串
{
if(isNumber (zzexpr[i])) //如果是数字 直接输出
{
hzexpr[j++] = zzexpr[i];
}
else if(isOperator (zzexpr[i]))//如果是操作符 判断优先级
{
hzexpr[j++] = ' ';
// 若栈顶优先级不低,将栈顶符号弹出,之后进栈
while((LinkStack_Size (list) > 0) && (priority (zzexpr[i]) <= priority ((char) (int) LinkStack_Top (list))))
{
hzexpr[j++] = (char) (int) LinkStack_Pop (list);
}
// 若栈顶符号优先级低,符号进栈
LinkStack_Push (list, (void *) (int) zzexpr[i]);
}
else if(isLeft (zzexpr[i]))//如果是左括号 直接入栈
{
LinkStack_Push (list, (void *) (int) zzexpr[i]);
}
else if(isRight (zzexpr[i])) //如果是右括号,将栈顶符号弹出并输出,直到匹配到左括号
{
while(!isLeft ((char) (int) LinkStack_Top (list)))
{
hzexpr[j++] = ' ';
hzexpr[j++] = (char) (int) LinkStack_Pop (list);
}
LinkStack_Pop (list);
}
else if((zzexpr[i]) == ' ');
else
{
printf ("Invalid expression!\n");
break;
}
i++;
}
//遍历结束:栈中所有符号弹出并输出
while((LinkStack_Size (list) > 0) && (zzexpr[i] == '\0'))
{
hzexpr[j++] = ' ';
hzexpr[j++] = (char) (int) LinkStack_Pop (list);
}
hzexpr[j] = '\0';
LinkStack_Destroy (list);
return hzexpr;
}
int calculation(const char *hzexpr) //计算后缀表达式
{
int ret = 0;
int i = 0;
char strnum[16];
LinkStack *stack = LinkStack_Create ();
while(hzexpr[i] != '\0')
{
if(isNumber (hzexpr[i]))//对于数字:进栈
{
memset (strnum, 0, 16);
for(int j = 0; isNumber (hzexpr[i]); ++j)
{
strnum[j] = hzexpr[i];
i++;
}
int tmpnum = myStr2Int (strnum);
LinkStack_Push (stack, (void *) tmpnum);
}
else if(isOperator (hzexpr[i]))
{
/* 对于符号:
- 从栈中弹出右操作数
- 从栈中弹出左操作符
- 根据符号运算
- 把运算结果压入栈中
*/
int right = (int) LinkStack_Pop (stack);
int left = (int) LinkStack_Pop (stack);
int result = express (left, right, hzexpr[i]);
LinkStack_Push (stack, (void *) result);
}
else if((hzexpr[i]) == ' ');
else
{
printf ("Invalid expression!\n");
break;
}
i++;
}
//遍历结束:栈中唯一数字为操作结果
if((LinkStack_Size (stack) == 1) && (hzexpr[i] == '\0'))
{
ret = (int) LinkStack_Pop (stack);
}
else
{
printf ("invalid expression\n");
}
LinkStack_Destroy (stack);
return ret;
}
int scanner(const char *code);
int main_zz2hzexpr()
{
const char *expr = "8*(6+2*4+3)-5*11*2+3*4+18/3-15";
char hzbds[128];
if(scanner (expr))//括号匹配
{
printf ("Successful matching\n");
printf ("zzexpr:%s\n", expr);
printf ("hzexpr:%s\n", transform (expr, hzbds));
printf ("result:%d\n", calculation (hzbds));
}
else
{
printf ("result:match fails!\n");
}
return 0;
}