中缀表达式求值
基于栈的两种不同的方法求值
第一种:先将中缀表达式转化为后缀表达式(逆波兰表达式),再将后缀表达式求值
第二种:利用两个栈直接求值
以下分别介绍两种方法
第一种:
1、利用栈先将中缀表达式转换为后缀表达式
2、然后利用栈求后缀表达式的值
【对应步骤具体操作】
1、先将中缀表达式转换为后缀表达式(注意:中缀表达式中数字和运算符之间没有空格,转换为后缀表达式后数字和运算符、数字和数字、运算符与运算符中间有空格,方便运算)
(1)依次扫描中缀表达式
(2)遇到数字输出到后缀表达式
(3)遇到运算符,有以下几种情况
a:栈空直接入栈
b:遇到’(‘直接入栈
c:遇到’)‘一直出栈并输出,直到’(‘出栈为止,但’('不作为输出(因为后缀表达式中没有括号)
d:遇到运算符优先级高于栈顶运算符优先级,则入栈
e:遇到运算符优先级低于或等于栈顶运算符优先级,则出栈,直到其优先级高于栈顶运算符优先级时停止(或栈为空),最后再将其入栈
2、计算后缀表达式
(1)依次扫描后缀表达式
(2)遇到数值入栈
(3)遇到符号将栈顶两个元素进行相应运算,将运算结果再入栈,重复(1)(2)操作,直到扫描结束
【代码实现】
#include <stdio.h>
#define MAXSIZE 100
//判断表达式的优先级
int symcmp(char a, char b)
{
if (b == '(')
return 1;
else if ((b == '*' || b == '/') && (a == '+' || a == '-' || a == '('))
return 1;
else if ((b == '+' || b == '-') && (a == '('))
return 1;
else
return 0;
}
//中缀表达式转换为后缀表达式
void exp_transplant(char *str1, char *str2)
{
char stack[MAXSIZE];//栈
int top = -1;//栈顶指针
int j = 0;
for (int i = 0; str1[i] != '\0'; i++)
{
if (str1[i] >= '0' && str1[i] <= '9') //数字直接输出
str2[j++] = str1[i];
else
{
if (i != 0 && str2[j - 1] != ' ') //之间加空格
str2[j++] = ' ';
if (str1[i] == ')') //一直出栈并输出,直到'('出栈,但'('不输出
{
while (stack[top] != '(')
{
str2[j++] = stack[top--];
str2[j++] = ' ';
}
top--;
}
else if (!symcmp(stack[top], str1[i])) //运算符优先级低,则出栈
{
while (top > -1 && (!symcmp(stack[top], str1[i]))) //要么栈为空、要么优先级为高,则停止出栈
{
str2[j++] = stack[top--];
str2[j++] = ' ';
}
stack[++top] = str1[i];
}
else
{
stack[++top] = str1[i];
}
}
}
if (str2[j - 1] != ' ')
str2[j++] = ' ';
while (top > -1) //将栈中剩余的运算符输出
{
str2[j++] = stack[top--];
str2[j++] = ' ';
}
str2[j - 1] = '\0';//方便后面计算后缀表达式
}
//计算后缀表达式
int cal_s(char *str)
{
int stack[MAXSIZE];
int top = -1, tmp = 0, k = 10;
for (int i = 0; str[i] != '\0'; i++)
{
if (str[i] >= '0' && str[i] <= '9') //计算数值
tmp = tmp * 10 + str[i] - '0';
else if (str[i] == ' ') //遇到' '就入栈(入的是上一个for循环的tmp值)
{
stack[++top] = tmp;
tmp = 0; //设置为0,计算下一个数值
}
else //遇到运算符进入,拿栈顶两个元素进行相应运算
{
switch (str[i])
{
case '+':tmp = stack[top - 1] + stack[top]; break;
case '-':tmp = stack[top - 1] - stack[top]; break;
case '*':tmp = stack[top - 1] * stack[top]; break;
case '/':tmp = stack[top - 1] / stack[top]; break;
}
top -= 2;
}
}
stack[++top] = tmp; //后缀表达式中最后一个运算符后没有空格,所有整个表达式的最后结果就没有入栈
return stack[0];
}
//计算中缀表达式
int calculate_expression(char *str)
{
char s[100]; //存放后缀表达式
exp_transplant(str, s); //将中缀表达式转换为后缀表达式
int ret = cal_s(s); //计算后缀表达式
return ret;
}
int main()
{
char *str = "50+7*3*(2+1)-3";
int ret = calculate_expression(str);
printf("表达式的结果是:%d\n", ret);
return 0;
}
第二种:
利用两个栈直接求结果,一个是运算值栈(数值入的栈),一个是运算符栈(运算符入的栈)
【对应步骤具体操作】
(1)依次扫描中缀表达式
(2)遇到运算值直接入栈
(3)遇到运算符,有以下几种情况
a:栈空直接入栈
b:遇到’(‘直接入栈
c:遇到’)‘一直出栈并拿运算值栈中的栈顶两个元素做相应的运算,直到’('出栈为止。(栈顶两个元素运算时注意次序,栈顶第二个运算值在前,第一个在后,例如:a为栈顶元素,b为此栈顶元素,两值做减法运算,b-a)
d:遇到运算符优先级高于栈顶运算符优先级,则入栈
e:遇到运算符优先级低于或等于栈顶运算符优先级,则出栈,直到其优先级高于栈顶运算符优先级时停止(或栈为空),最后再将其入栈
f:直到中缀表达式扫描结束
(4)中缀表达式扫描结束后,如果运算符栈中还有运算符,一直出栈并与运算值栈做相应操作(与步骤(3)中c的操作相同),直到栈空
(5)此时运算值栈中剩一个元素,即为最终结果
【代码实现】
#include <stdio.h>
#include <ctype.h>
#define MAXSIZE 100
//判断表达式的优先级
int symcmp(char a, char b)
{
if (b == '(')
return 1;
else if ((b == '*' || b == '/') && (a == '+' || a == '-' || a == '('))
return 1;
else if ((b == '+' || b == '-') && (a == '('))
return 1;
else
return 0;
}
//计算运算值栈顶两个元素(a栈顶第一个元素,b栈顶第二个元素)
int calculate(char c,int a,int b)
{
int tmp = 0;
switch (c)
{
case '+':tmp = b + a; break;
case '-':tmp = b - a; break;
case '*':tmp = b * a; break;
case '/':tmp = b / a; break;
}
return tmp;
}
//计算中缀表达式
int calculate_expression(char *str)
{
int num_stack[MAXSIZE]; //运算值栈
int num_top = -1; //运算值栈指针
char sym_stack[MAXSIZE]; //操作符栈
int sym_top = -1; //操作符栈指针
int i = 0;
while (str[i] != '\0')
{
if (isdigit(str[i]))//判断是否是数字字符
{
//将数字字符转换为数值型并入栈
int val = 0;
while (isdigit(str[i]))
{
val = val * 10 + str[i] - '0';
i++;
}
num_stack[++num_top] = val;
}
else //符号
{
if (str[i] == ')')
{
while (sym_stack[sym_top] != '(')
{
int ret = calculate(sym_stack[sym_top], num_stack[num_top], num_stack[num_top - 1]); //计算栈顶两个元素
sym_top--;
num_top -= 2;
num_stack[++num_top] = ret;
}
sym_top--;
i++;
}
else if (!symcmp(sym_stack[sym_top], str[i]))
{
while (sym_top > -1 && (!symcmp(sym_stack[sym_top], str[i])))
{
int ret = calculate(sym_stack[sym_top], num_stack[num_top], num_stack[num_top - 1]); //计算栈顶两个元素
sym_top--;
num_top -= 2;
num_stack[++num_top] = ret;
}
sym_stack[++sym_top] = str[i];
i++;
}
else
{
sym_stack[++sym_top] = str[i];
i++;
}
}
}
while (sym_top > -1)
{
int ret = calculate(sym_stack[sym_top], num_stack[num_top], num_stack[num_top - 1]); //计算栈顶两个元素
sym_top--;
num_top -= 2;
num_stack[++num_top] = ret;
}
return num_stack[0];
}
int main()
{
char *str = "50+3*(2+1)-5*5*(5+5)";
int ret = calculate_expression(str);
printf("表达式的结果是:%d\n", ret);
return 0;
}
OK!!!到此结束。如果有什么问题,希望友友们多多指教,共同进步!加油!加油!加油!