前言
复习到到队列和栈时涉及到了不太清楚的“中缀转化成后缀”的过程,专题中有写,就记录下来
正文
手工算法
参考:https://blog.csdn.net/qq_29462849/article/details/93649198
- 按运算符优先级对所有运算符和它的运算数加括号,(原本的括号不用加)
- 把运算符移到对应的括号后
- 去掉括号
具体例如:
a/b+(c∗d-e∗f)/g
加括号后式子变成:
((a/b)+(((c∗d)-(e∗f))/g))
把运算符移动到对应括号后面,再去掉括号:
ab/cd∗ef∗-g/+
代码
算法步骤
参考资料中的步骤
- 从左到右读进中序表达式的每个字符。
- 如果读到的字符为操作数,则直接输出到后缀表达式的数组。
- 如果遇到“( ”,也将其放入栈中。
- 如果遇到“ )”,则将栈顶元素弹出,将弹出的操作数输出到后缀数组中,直到遇到左括号为止,注意,左括号只弹出并不输出到后缀表达式中。
- 如果遇到操作符,当栈为空时,直接入栈,栈不空时,判断栈顶元素操作符优先级是否比当前操作符小,小的话直接把当前操作符进栈,不小的话栈顶元素输出到后缀数组中,直到栈顶元素操作符优先级比当前操作符小,再入栈。
- 如果我们读到了输入的末尾,则将栈中所有元素依次弹出输出到后缀表达式中
查阅网络发现有更方便记忆的算法
来自:https://blog.csdn.net/qq_42552533/article/details/86594681
- 从左向右顺序获取中缀表达式,数字直接输出
- 遇到左括号直接入栈
- 遇到右括号将栈中左括号之后入栈的运算符全部出栈输出,注意,左括号出栈但是不输出。
- 遇到加号和减号,如果此时栈空,则直接入栈,将栈中优先级不小于的运算符依次出栈(注意:加号和减号属于同一个优先级,所以也依次弹栈)直到栈空或则遇到左括号为止,停止出栈。
- 遇到乘号和除号直接入栈,直到遇到优先级比它更低的运算符,依次出栈。
- 获取完后,将栈中剩余的运算符号依次出栈输出
/*中缀转后缀函数*/
void Change(Stack *S,Elemtype str[])
{
int i=0;
Elemtype e;
InitStack(S);
while(str[i]!='\0')
{
while(isdigit(str[i]))
{/*过滤数字字符,直接输出,直到下一位不是数字字符打印空格跳出循环 */
printf("%c",str[i++]);
if(!isdigit(str[i]))
{
printf(" ");
}
}
if(str[i]=='+'||str[i]=='-')
{
if(StackEmpty(S))//栈空直接入栈
{
Push(S,str[i]);
}
else
{
do
{
Pop(S,&e);
if(e=='(')
{
Push(S,e);
}
else
{
printf("%c ",e);
}
}while(!StackEmpty(S) && e != '(' );//否则出栈,直到栈空或遇到左括号
Push(S,str[i]);
}
}
/*当遇到右括号是,把括号里剩余的运算符弹出,直到匹配到左括号为止
左括号只弹出不打印(右括号也不压栈)*/
else if(str[i]==')')
{
Pop(S,&e);
while(e!='(')
{
printf("%c ",e);
Pop(S,&e);
}
}
/*乘、除、左括号都是优先级高的,直接压栈*/
else if(str[i]=='*'||str[i]=='/'||str[i]=='(')
{
Push(S,str[i]);
}
else if(str[i]=='\0')
{
break;
}
else
{
printf("\n输入格式错误!\n");
return ;
}
i++;
}
/*最后把栈中剩余的运算符依次弹栈打印*/
while(!StackEmpty(S))
{
Pop(S,&e);
printf("%c ",e);
}
}