[

](https://www.zhihu.com/search?type=content&q=%E4%B8%AD%E7%BC%80%E8%A1%A8%E8%BE%BE%E5%BC%8F%E8%BD%AC%E5%90%8E%E7%BC%80%E8%A1%A8%E8%BE%BE%E5%BC%8F)
优先级:https://zhuanlan.zhihu.com/p/422390012
中缀表达式中,优先级:{ (, ) } > { *, / } > { +, - }
注意,同级运算中,先出现的(左侧)优先级高。
后缀表达式中,出现的运算符优先与操作数结合。即,优先级:{ 靠前 } > { 靠后 }

换元法:https://zhuanlan.zhihu.com/p/135433833
在表达式求值的过程中,常用到将中缀表达式转化为后缀表达式前缀表达式的过程
我们常见的表达式形式为中缀表达式,对于简单的中缀表达式可以很容易转化为前缀表达式或后缀表达式
例如,中缀表达式a+b,其前缀表达式为+ab,后缀表达式为ab+
较复杂的表达式则不易直接得出结果,这里我们将通过来实现相应的转化
示例表达式:[(A+B)*C]-[E-F]
转化为前缀表达式:

  1. 先计算A+B,转化为+AB
  2. +AB作为整体与C运算,转化为*+ABC
  3. 运算E-F,转化为-EF
  4. +ABC与E-F都作为整体执行-运算,转化为**-+ABC-EF**

转化为后缀表达式:

  1. 先计算A+B,转化为AB+
  2. AB+作为整体与C运算,转化为AB+C*
  3. 运算E-F,转化为EF-
  4. 将AB+C与EF-作为整体执行-运算,转化为**AB+CEF—**

    算法思想

    如果检测到数字,则直接加入到后缀表达式中
    如果检测到运算符时:
  1. 若为‘(’,入栈
  2. 若为‘)’,则依次将栈中的运算符加入后缀表达式,直到出现‘(’,并从栈中删除‘(’
  3. 若为‘+’,‘-’,‘*’,‘/’
  • 栈空,入栈
  • 栈顶元素为‘(’,入栈
  • 高于栈顶元素优先级,入栈
  • 否则,依次弹出栈顶运算符,直到一个优先级比它低的运算符或‘(’为止

遍历完成,若栈非空,依次弹出栈中所有元素
该算法使得栈顶运算符处于较高优先级,并先弹出栈,进入后缀表达式

过程分析

示例:((A+B)C)-(E-F)
1.连续两个’(’,入栈
(当前后缀表达式: )
image.png
前缀表达式遍历进度((
2.遍历到数字A,加入到后缀表达式
(当前后缀表达式:A)
image.png
前缀表达式遍历进度((A
3.遍历到运算符+,由于栈顶元素为‘(’,直接入栈。
(当前后缀表达式:A)
4.接着遍历数字B,加入到后缀表达式
(当前后缀表达式:AB)
image.png
前缀表达式遍历进度((A+B
5.遍历‘)’,依次将栈中的运算符加入后缀表达式,直到出现‘(’,并删除栈顶的‘(’
(当前后缀表达式:AB+)
注:括号是不会出现在后缀表达式或前缀表达式中的
image.png
前缀表达式遍历进度((A+B)
6.遍历到
,栈顶为‘(’,直接入栈
7.接着遍历数字C,直接加入到后缀表达式中
(当前后缀表达式:AB+C)
image.png
前缀表达式遍历进度((A+B)C
8.继续遍历到‘)’,依次将栈中的运算符加入后缀表达式,直到出现‘(’,并删除栈顶的‘(’
【当前后缀表达式:AB+C

image.png
前缀表达式遍历进度((A+B)C)
9.接着遍历到-,栈空,入栈
【当前后缀表达式:AB+C

image.png
前缀表达式遍历进度((A+B)C)-
10.遍历‘(’,直接入栈
【当前后缀表达式:AB+C

image.png
前缀表达式遍历进度((A+B)C)-(
11.遍历到数字E,直接加入到后缀表达式
【当前后缀表达式:AB+C
E】
12.遍历到-,栈顶元素为‘(’,入栈
【当前后缀表达式:AB+CE】
13.遍历到F,加入到后缀表达式
【当前后缀表达式:AB+C
EF】
image.png
前缀表达式遍历进度((A+B)C)-(E-F
14.遍历到‘)’,依次将栈中的运算符加入后缀表达式,直到出现‘(’,并删除栈顶的‘(’
【当前后缀表达式:AB+C
EF-】
image.png
前缀表达式遍历进度((A+B)C)-(E-F)遍历完毕
15.遍历完毕,栈非空,将栈中元素依次弹出
【当前后缀表达式:AB+C
EF—】
image.png
成功得到后缀表达式!!!

代码实现

  1. #include<stdio.h>
  2. #define ElemType char
  3. #define MaxSize 50
  4. typedef struct {
  5. ElemType data[MaxSize];
  6. int top;
  7. }SqStack;
  8. void initStack(SqStack& S)
  9. {
  10. S.top = -1; //初始化栈顶指针
  11. }
  12. bool StackEmpty(SqStack S)
  13. {
  14. if (S.top == -1) //栈空
  15. return true;
  16. else
  17. return false; //栈不空
  18. }
  19. bool Push(SqStack& S, ElemType x)
  20. {
  21. if (S.top == MaxSize - 1) //栈满 不能执行入栈操作
  22. return false;
  23. S.top++; //指针先加1,再入栈
  24. S.data[S.top] = x;
  25. return true;
  26. }
  27. bool Pop(SqStack& S, ElemType& x)
  28. {
  29. if (S.top == -1) //栈空 不能执行出栈操作
  30. return false;
  31. x = S.data[S.top]; //先出栈 指针再减1
  32. S.top--;
  33. return true;
  34. }
  35. bool GetPop(SqStack S, ElemType& x)
  36. {
  37. if (S.top == -1) //栈空报错
  38. return false;
  39. x = S.data[S.top]; //用x存储栈顶元素
  40. return true;
  41. }
  42. int main()
  43. {
  44. SqStack S;
  45. initStack(S);
  46. char NifixExpression[] = { '(','(','A','+','B',')','*','C',')','-','(','E','-','F',')','\0' };
  47. char PostfixExpression[60]; //在字符数组最后添加'\0',作为结束标志
  48. int index = 0;
  49. char* p = NifixExpression;
  50. while (*p!='\0')
  51. {
  52. if (*p == '(') //如果为左括号,直接入栈
  53. {
  54. Push(S, *p);
  55. p++;
  56. }
  57. else if (*p == ')')//若为右括号,依次弹出栈中运算符,直到'(',并删除'('--用出栈不保存数据实现
  58. {
  59. while (S.data[S.top] != '(')
  60. {
  61. char temp;
  62. Pop(S, temp);
  63. if (temp == '+' || temp == '-' || temp == '*' || temp == '/')
  64. {
  65. PostfixExpression[index] = temp;
  66. index++;
  67. }
  68. }
  69. char temp;
  70. Pop(S, temp); //把左括号也出栈
  71. p++;
  72. }
  73. else if (*p >= 'A' && *p <= 'Z') //这里用大写字母代替表达式中的数字,为大写字母则直接进入后缀表达式
  74. {
  75. PostfixExpression[index] = *p;
  76. index++;
  77. p++;
  78. }
  79. else
  80. {
  81. if (*p == '+' || *p == '-')
  82. {
  83. if (S.data[S.top] == '('||StackEmpty)//如果遍历到'+''-',且栈为空或栈顶为'(',直接入栈
  84. {
  85. Push(S, *p);
  86. p++;
  87. }
  88. else {
  89. while (S.data[S.top] != '('&&!StackEmpty)//依次弹出较高优先级运算符,直到'('
  90. {
  91. char temp;
  92. Pop(S, temp);
  93. PostfixExpression[index] = temp;
  94. index++;
  95. }
  96. }
  97. }
  98. else
  99. {
  100. Push(S, *p);
  101. p++;
  102. }
  103. }
  104. }
  105. if (!StackEmpty(S)) //若栈不为空,依次弹出其中的运算符
  106. {
  107. while (S.top != -1)
  108. {
  109. char temp;
  110. Pop(S,temp);
  111. PostfixExpression[index] = temp;
  112. index++;
  113. }
  114. }
  115. PostfixExpression[index] = '\0'; //在字符数组后加'\0',作为结束标志
  116. printf("中缀表达式为:%s",NifixExpression);
  117. printf("\n");
  118. printf("后缀表达式为:%s", PostfixExpression);
  119. }