题目描述
其实呢,这玩意简单啊,把我之前这张图拿过来:
意思就是,利用后缀表达式计算运算符的结果(注意后缀表达式是没有括号的):
分析思路
后缀表达式的优点就是,我们没要记住运算符的优先级,符号进来,直接拿两个数出来运算,在压入栈里面就行。
这里我做了一个输入正常表达式,然后转换成后缀表达式,然后在计算,注意,表达式之间每一个数字之间,数字与操作符之间是有空格的,主要是方便区分数字。
代码
demo.cpp
#include <cstdio>
#include <cstdlib>
extern "C" {
#include "linkstack.h"
}
//把中缀变后缀
void transfer_suffix(char infix[],char suffix[],link_stack *p_head)
{
int index = 0,cursor = 0;
while(infix[index] != '\0') {
char ch = infix[index];
//判断数字拼接,数字直接输出
if(ch >= '0' && ch <= '9') {
while(1) {
if(infix[index] < '0' || infix[index] > '9') {
break;
}
suffix[cursor++] = infix[index++];
}
//数字拼完了之后,后面还有一个空格别忘了
suffix[cursor++] = ' ';
}
//下面所有的部分都要开始入栈出栈操作(这里面都是非数字)
//上面数字拼接就会把index指针循环到非数字的部分
if(is_empty(p_head)) {
//这里不能拿ch来压,把index指向的部分压过来
push_stack(p_head,infix[index]);
//下面这部分,就分为(括号入栈,栈顶高优先级出栈,栈顶低优先级进栈
} else if(!is_empty(p_head) && infix[index] != '\0') {//这里必须把'\0'加进来,上面index可能走到结尾
char oper_ch = infix[index];
char top_ch = (char)top_stack(p_head);
//如果是左括号直接进栈
if(oper_ch == '(') {
push_stack(p_head,(int)oper_ch);
//栈顶优先级高,先出栈在进栈,直到遇到(
} else if(top_ch == '*' && (oper_ch == '+' || oper_ch == '-')) {
//这个时候,先出栈,在进栈
while(top_ch != '(') {
suffix[cursor++] == top_ch;
suffix[cursor++] = ' ';
//先把栈弹出再取栈顶进行判断
pop_stack(p_head);
top_ch = (char)top_stack(p_head);
}
//出栈之后,把当前符号入栈
push_stack(p_head,(int)oper_ch);
//栈顶优先级低,直接进栈
} else if((top_ch == '+' || top_ch == '-' || top_ch == '(') && (oper_ch != ')')) {
//直接进栈
push_stack(p_head,(int)oper_ch);
//下面考虑出栈并输出
} else if (oper_ch == ')') {
//注意栈顶元素是已经有了
while(top_ch != '(') {
suffix[cursor++] = top_ch;
suffix[cursor++] = ' ';
pop_stack(p_head);
top_ch = (char)top_stack(p_head);
}
//上面出栈输出之后,把'('出栈
pop_stack(p_head);
}
/*进栈出栈的大if*/
}
index++;//整体循环字符串
/**while大循环结束*/
}
//整体循环完毕,把栈里面内容输出
//栈里面是可能还有符号的
while(!is_empty(p_head)) {
suffix[cursor++] = (char) top_stack(p_head);
suffix[cursor++] = ' ';
pop_stack(p_head);
}
}
//开始进行后缀表达式计算
//程序整体结束之后就只会有一个结果在栈里面
void calc_suffix(link_stack *stack,char *suffix)
{
int index = 0;
char num_arr[20] = {'\0'};//存放数字的字符串
int cursor = 0;
int res = 0;//保存最后的结果集
while(suffix[index] != '\0') {
char ch = suffix[index];
//还是做一个数字拼接,如果是数字直接入栈
if(ch >= '0' && ch <= '9') {
cursor = 0;//这个游标设定每次从头开始拼接数字
while(1) {
if(suffix[index] < '0' || suffix[index] > '9') {
num_arr[index] = '\0';//这里必须限定
break;
}
num_arr[cursor++] = suffix[index++];
}
//把字符串变成整型
//atoi把字符串变成整型
int num = atoi(num_arr);
push_stack(stack,num);
} else if(suffix[index] == ' ') {
index++;//这里很可能会直接指向了一个数值,然后进行下一个循环
//换句话说index++,要放到else里面
} else {
char oper = suffix[index];
//拿到操作符号进行判定
if(oper == '*' || oper == '+' || oper == '-') {
//把栈上面的两个操作数拿过来
//左右操作数别拿反了,在栈上面是有前后顺序的
int right_num = top_stack(stack);
pop_stack(stack);
int left_num = top_stack(stack);
pop_stack(stack);
if(oper == '*') {
res = left_num * right_num;
} else if(oper == '+') {
res = left_num + right_num;
} else if(oper == '-') {
res = left_num - right_num;
}
//把当前结果集压入到栈里面
push_stack(stack,res);
}
index++;//走到符号部分进行index++往前走
}
/**大while循环结束**/
}
}
int main()
{
char infix[100] = {'\0'};
char suffix[100] = {'\0'};
link_stack *p_head = create_stack();
while(scanf("%s",infix) != EOF && p_head != NULL) {
transfer_suffix(infix,suffix,p_head);
printf("%s\n",suffix);
calc_suffix(p_head,suffix);
printf("%d\n",top_stack(p_head));
pop_stack(p_head);
}
return 0;
}
运行结果: