当前位置:   article > 正文

【数据结构】【栈(stack)应用】四则运算表达式求值(支持括号、负数)_用计算机实现整数带括号四则运算 数据结构

用计算机实现整数带括号四则运算 数据结构

前言:

        先理解原理,再看代码,注意标红字体很重要!结尾附完整测试代码,C语言实现!

更新留言:

        本来是侧重演示栈结构的使用,后面评论区发现很多朋友对这个四则运算比较感兴趣,特此做了更新,新增了对负数的运算支持。

        若您也有新的想法或者需求,请在评论区留言,我将尽可能的实现。需要代码的朋友请直接在章末获取。

        再次感谢您的阅览,谢谢!(更新时间2023年12月05日)

一、四则运算表达式求值

        栈的现实应用也很多,这里重点讲一下比较常见的应用:数学表达式的求值。进入正题之前先讲一下逆波兰的含义。

1.逆波兰(后缀)表达式

        对于“9+(3-1)×3+10÷2”,如果要用后缀表示法应该是什么样子:“9 3 1-3*+102/+”,这样的表达式称为后缀表达式,叫后缀的原因在于所有的符号都是在要运算数字的后面出现。

        请参考下图熟悉一下逆波兰表达式,不需要纠结。

2.后缀表达式计算结果

        计算机如何应用后缀表达式表示“9+(3-1)×3+10÷2”的:

        后缀表达式:9 3 1-3*+10 2/+

        规则:

  • 遍历后缀表达式,如果遇到数字则直接入栈,如果遇到操作符,则弹出栈顶的两个元素,进行计算后将结果入栈。
  • 最终,栈内剩余的元素就是整个表达式的计算结果。

图文演示:

1)初始化一个空栈。此栈用来对要运算的数字进出使用。如下图中左图所示。

2)后缀表达式中前三个都是数字,所以9、3、1进栈。如下图中右图所示。

 3)接下来是“-”,所以将栈中的1出栈作为减数,3出栈作为被减数,并运算3-1得到 2,再将2进栈,如下图中左图所示。

4)接着是数字3进栈,如下图中右图所示。 

5)后面是“*”,也就意味着栈中3和2出栈,2与3相乘,得到6,并将6进栈,如下图中左图所示。

6)下面是“+”,所以栈中6和9出栈,9与6相加,得到15,将15进栈,如下图中右图所示。

7)接着是10与2两数字进栈,如下图中左图所示。

8)接下来是符号“/”,因此,栈顶的2与10出栈,10与2相除,得到5,将5进栈,如下图中右图所示。

 9)最后一个是符号“+”,所以15与5出栈并相加,得到20,将20进栈,如下图中左图所示。

10)结果是20出栈,栈变为空,如下图中右图所示。

注:如果对后缀表达式“9 3 1-3+10 2/+”是怎么出来的?这个问题有疑问的。请继续往下看中缀表达式转后缀表达式。

3.中缀表达式转后缀表达式

        我们把平时所用的标准四则运算表达式,即“9+(3-1)×3+10÷2”叫做中缀表达式。因为所有的运算符号都在两数字的中间,现在我们的问题就是中缀到后缀的转化。

        中缀表达式“9+(3-1)×3+10÷2”转化为后缀表达式“9 3 1-3*+10 2/+”

规则:

  1. 遇到数字就直接输出到后缀表达式中,遇到操作符就判断其优先级,并将其压入栈中。
  2. 如果栈顶元素的优先级大于等于当前操作符,则先将栈顶元素弹出并输出到后缀表达式中,再将当前操作符压入栈中。
  3. 如果遇到了左括号,则直接将其压入栈中,如果遇到了右括号,则弹出栈中的元素,直到遇到了左括号为止,并将这些元素输出到后缀表达式中。
  4. 最后,将栈中剩余的元素依次弹出,并输出到后缀表达式中。

图文演示:

1)初始化一空栈,用来对符号进出栈使用。如下图的左图所示。

2)第一个字符是数字9,输出9,后面是符号“+”,进栈。如下图的右图所示。

3)第三个字符是“(”,依然是符号,因其只是左括号,还未配对,故进栈。如下图的左图所示。

4)第四个字符是数字3,输出,总表达式为93,接着是“-”,进栈。如下图的右图所示。

5)接下来是数字1,输出,总表达式为 9 31,后面是符号“)”,此时,我们需要去匹配 此前的“(”,所以栈顶依次出栈,并输出,直到“(”出栈为止。此时左括号上方只有“-”, 因此输出“-”。总的输出表达式为 9 3 1-。如下图的左图所示。

6)紧接着是符号“×”,因为此时的栈顶符号为“+”号,优先级低于“×”,因此不输出,“*”进栈。接着是数字3,输出,总的表达式为 9 3 1-3。如下图的右图所示。

7)之后是符号“+”,此时当前栈顶元素“”比这个“+”的优先级高,因此栈中元素出栈并输出(没有比“+”号更低的优先级,所以全部出栈),总输出表达式为9 3 1-3+。然后将当前这个符号“+”进栈。也就是说,前6张图的栈底的“+”是指中缀表达式中开头的9 后面那个“+”,而下图的左图中的栈底(也是栈顶)的“+”是指“9+(3-1)×3+”中的最后 一个“+”。

8)紧接着数字10,输出,总表达式变为9 31-3*+10。后是符号“÷”,所以“/”进栈。如下图的右图所示。

 9)最后一个数字2,输出,总的表达式为9 31-3+10 2。如下图的左图所示。

10)因已经到最后,所以将栈中符号全部出栈并输出。最终输出的后缀表达式结果为 93 1-3+10 2/+。如下图的右图所示。

        从刚才的推导中你会发现,要想让计算机具有处理我们通常的标准(中缀)表达式的能力,最重要的就是两步:

        1.将中缀表达式转化为后缀表达式(栈用来进出运算的符号)。

        2.将后缀表达式进行运算得出结果(栈用来进出运算的数字)。

        整个过程,都充分利用了栈的后进先出特性来处理,理解好它其实也就理解好了栈这个数据结构。

        接下来就是代码实现了。

4.代码实现

        请务必看懂前面两节的内容,思路和原理往往比代码更重要!!!

代码分三部分:

        1)栈结构的构造(C语言实现)

        2)中缀表达式转化为后缀表达式(栈用来进出运算的符号)

        3)后缀表达式进行运算得出结果(栈用来进出运算的数字)

4.1栈结构构造

  1. typedef struct {
  2. double* data; // 数组指针
  3. int top; // 栈顶指针
  4. int size; // 栈的大小
  5. } Stack;
  6. // 初始化栈
  7. void initStack(Stack* s, int size) {
  8. s->data = (double*)malloc(sizeof(double) * size);// 动态分配数组内存
  9. s->top = -1;
  10. s->size = size;
  11. }
  12. // 判断栈是否为空
  13. int isEmpty(Stack* s) {
  14. return s->top == -1;
  15. }
  16. // 判断栈是否已满
  17. int isFull(Stack* s) {
  18. return s->top == s->size - 1;
  19. }
  20. // 入栈
  21. void push(Stack* s, double value) {
  22. if (isFull(s)) { // 检查栈是否已满
  23. printf("Stack overflow\n");
  24. exit(1); // 若栈已满,则退出程序
  25. }
  26. s->top++; // 栈顶指针加1
  27. s->data[s->top] = value; // 在栈顶插入新值
  28. }
  29. // 出栈
  30. double pop(Stack* s) {
  31. if (isEmpty(s)) { // 检查栈是否为空
  32. printf("Stack underflow\n");
  33. exit(1); // 若栈为空,则退出程序
  34. }
  35. double value = s->data[s->top]; // 储存栈顶元素的值
  36. s->top--; // 栈顶指针减1
  37. return value; // 返回栈顶元素的值
  38. }
  39. // 获取栈顶元素
  40. double top(Stack* s) {
  41. if (isEmpty(s)) { // 检查栈是否为空
  42. printf("Stack underflow\n");
  43. exit(1); // 若栈为空,则退出程序
  44. }
  45. return s->data[s->top]; // 返回栈顶元素的值
  46. }

4.2将中缀转换成后缀

  1. // 将中缀表达式转换成后缀表达式
  2. void infixToPostfix(char* infix, char* postfix) {
  3. Stack s;
  4. initStack(&s, 100);// 初始化栈
  5. char* p = infix;// 使用指针遍历中缀表达式
  6. char* q = postfix;// 使用指针储存后缀表达式
  7. while (*p != '\0') {// 如果当前位置不为空
  8. if (isdigit(*p)) {// 如果当前位置是数字
  9. while (isdigit(*p) || *p == '.') {
  10. *q = *p;// 直接输出
  11. q++;
  12. p++;
  13. }
  14. *q = ' ';
  15. q++;
  16. }
  17. else if (*p == '+' || *p == '-' || *p == '*' || *p == '/') {// 如果当前位置是运算符
  18. int priority1 = getPriority(*p);// 获取当前运算符的优先级
  19. while (!isEmpty(&s) && isOperator(top(&s)) && getPriority(top(&s)) >= priority1) {
  20. // 如果栈不空,栈顶为运算符,并且栈顶运算符的优先级大于等于当前运算符的优先级
  21. char op = pop(&s);// 将栈顶运算符弹出
  22. *q = op;// 将弹出的运算符输出到后缀表达式中
  23. q++;
  24. *q = ' ';// 输出空格
  25. q++;
  26. }
  27. push(&s, *p);// 将当前运算符入栈
  28. p++;
  29. }
  30. else if (*p == '(') {// 如果当前位置是左括号
  31. push(&s, *p);// 将其入栈
  32. p++;
  33. }
  34. else if (*p == ')') {// 如果当前位置是右括号
  35. while (!isEmpty(&s) && top(&s) != '(') {// 不断将栈中的元素弹出,直到遇到左括号
  36. char op = pop(&s);
  37. *q = op;// 将弹出的运算符输出到后缀表达式中
  38. q++;
  39. *q = ' ';// 输出空格
  40. q++;
  41. }
  42. if (!isEmpty(&s) && top(&s) == '(') {// 如果栈不空且栈顶元素是左括号
  43. pop(&s);// 将左括号弹出并丢弃
  44. }
  45. else {
  46. printf("Invalid expression: %s\n", infix);// 若遍历完中缀表达式后栈中仍然有元素,或遇到错误情况,则输出错误信息
  47. exit(1);
  48. }
  49. p++;
  50. }
  51. else {// 如果当前位置不是数字、运算符、左括号或右括号,直接跳过
  52. p++;
  53. }
  54. }
  55. while (!isEmpty(&s)) {// 如果栈不空,则将栈中所有元素弹出并输出到后缀表达式中
  56. char op = pop(&s);
  57. *q = op;
  58. q++;
  59. *q = ' ';// 输出空格
  60. q++;
  61. }
  62. *(q - 1) = '\0';// 给后缀表达式添加结束符
  63. }

4.3计算后缀表达式的值

  1. // 计算后缀表达式的值
  2. double evaluate(char* postfix) {
  3. Stack s;
  4. initStack(&s, 100);// 初始化栈
  5. char* p = postfix;// 使用指针遍历后缀表达式
  6. while (*p != '\0') {// 如果当前位置不为空
  7. if (isdigit(*p)) {// 如果当前位置是数字
  8. double num = *p - '0';// 获取数字的整数部分
  9. p++;
  10. while (isdigit(*p) || *p == '.') {// 继续读取小数部分
  11. if (*p == '.') { // 如果当前位置是小数点
  12. p++;
  13. double frac = 0.1;// 初始化分数
  14. while (isdigit(*p)) {// 继续读取小数部分
  15. num += (*p - '0') * frac;// 计算小数值
  16. p++;
  17. frac /= 10;// 分数部分减小
  18. }
  19. break; // 跳出读取小数值的循环
  20. }
  21. else {// 如果不是小数点,表示当前位置是数字
  22. num = num * 10 + (*p - '0');// 计算数字值
  23. p++;
  24. }
  25. }
  26. push(&s, num);// 将数字入栈
  27. }
  28. else if (*p == '+' || *p == '-' || *p == '*' || *p == '/') {// 如果当前位置是运算符
  29. double num2 = pop(&s);// 从栈中弹出栈顶元素作为第二个操作数
  30. double num1 = pop(&s);// 再从栈中弹出栈顶元素作为第一个操作数
  31. double result = operate(num1, num2, *p);// 利用operate函数计算出结果
  32. push(&s, result);// 将结果压入栈中
  33. p++;
  34. }
  35. else {
  36. p++;
  37. }
  38. }
  39. double value = pop(&s);
  40. return value;// 返回栈顶元素,即为最终结果
  41. }

完整测试代码:

  1. #define _CRT_SECURE_NO_WARNINGS 1
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <ctype.h>
  5. typedef struct {
  6. double* data; // 数组指针
  7. int top; // 栈顶指针
  8. int size; // 栈的大小
  9. } Stack;
  10. // 初始化栈
  11. void initStack(Stack* s, int size) {
  12. s->data = (double*)malloc(sizeof(double) * size);// 动态分配数组内存
  13. s->top = -1;
  14. s->size = size;
  15. }
  16. // 判断栈是否为空
  17. int isEmpty(Stack* s) {
  18. return s->top == -1;
  19. }
  20. // 判断栈是否已满
  21. int isFull(Stack* s) {
  22. return s->top == s->size - 1;
  23. }
  24. // 入栈
  25. void push(Stack* s, double value) {
  26. if (isFull(s)) { // 检查栈是否已满
  27. printf("Stack overflow\n");
  28. exit(1); // 若栈已满,则退出程序
  29. }
  30. s->top++; // 栈顶指针加1
  31. s->data[s->top] = value; // 在栈顶插入新值
  32. }
  33. // 出栈
  34. double pop(Stack* s) {
  35. if (isEmpty(s)) { // 检查栈是否为空
  36. printf("Stack underflow\n");
  37. exit(1); // 若栈为空,则退出程序
  38. }
  39. double value = s->data[s->top]; // 储存栈顶元素的值
  40. s->top--; // 栈顶指针减1
  41. return value; // 返回栈顶元素的值
  42. }
  43. // 获取栈顶元素
  44. double top(Stack* s) {
  45. if (isEmpty(s)) { // 检查栈是否为空
  46. printf("Stack underflow\n");
  47. exit(1); // 若栈为空,则退出程序
  48. }
  49. return s->data[s->top]; // 返回栈顶元素的值
  50. }
  51. // 判断是否为运算符
  52. int isOperator(char c) {
  53. return c == '+' || c == '-' || c == '*' || c == '/';
  54. }
  55. // 获取运算符优先级
  56. int getPriority(char op) {
  57. switch (op) {
  58. case '+':
  59. case '-':
  60. return 1;
  61. case '*':
  62. case '/':
  63. return 2;
  64. default:
  65. return 0;
  66. }
  67. }
  68. // 四则运算
  69. double operate(double num1, double num2, char op) {
  70. switch (op) {
  71. case '+':
  72. return num1 + num2;
  73. case '-':
  74. return num1 - num2;
  75. case '*':
  76. return num1 * num2;
  77. case '/':
  78. return num1 / num2;
  79. default:
  80. printf("Invalid operator: %c\n", op);
  81. exit(1);
  82. }
  83. }
  84. // 计算后缀表达式的值
  85. double evaluate(char* postfix) {
  86. Stack s;
  87. initStack(&s, 100);// 初始化栈
  88. char* p = postfix;// 使用指针遍历后缀表达式
  89. while (*p != '\0') {// 如果当前位置不为空
  90. if (isdigit(*p)) {// 如果当前位置是数字
  91. double num = *p - '0';// 获取数字的整数部分
  92. p++;
  93. while (isdigit(*p) || *p == '.') {// 继续读取小数部分
  94. if (*p == '.') { // 如果当前位置是小数点
  95. p++;
  96. double frac = 0.1;// 初始化分数
  97. while (isdigit(*p)) {// 继续读取小数部分
  98. num += (*p - '0') * frac;// 计算小数值
  99. p++;
  100. frac /= 10;// 分数部分减小
  101. }
  102. break; // 跳出读取小数值的循环
  103. }
  104. else {// 如果不是小数点,表示当前位置是数字
  105. num = num * 10 + (*p - '0');// 计算数字值
  106. p++;
  107. }
  108. }
  109. push(&s, num);// 将数字入栈
  110. }
  111. else if (*p == '+' || *p == '-' || *p == '*' || *p == '/') {// 如果当前位置是运算符
  112. double num2 = pop(&s);// 从栈中弹出栈顶元素作为第二个操作数
  113. double num1 = pop(&s);// 再从栈中弹出栈顶元素作为第一个操作数
  114. double result = operate(num1, num2, *p);// 利用operate函数计算出结果
  115. push(&s, result);// 将结果压入栈中
  116. p++;
  117. }
  118. else {
  119. p++;
  120. }
  121. }
  122. double value = pop(&s);
  123. return value;// 返回栈顶元素,即为最终结果
  124. }
  125. // 将中缀表达式转换成后缀表达式
  126. void infixToPostfix(char* infix, char* postfix) {
  127. Stack s;
  128. initStack(&s, 100);// 初始化栈
  129. char* p = infix;// 使用指针遍历中缀表达式
  130. char* q = postfix;// 使用指针储存后缀表达式
  131. while (*p != '\0') {// 如果当前位置不为空
  132. if (isdigit(*p)) {// 如果当前位置是数字
  133. while (isdigit(*p) || *p == '.') {
  134. *q = *p;// 直接输出
  135. q++;
  136. p++;
  137. }
  138. *q = ' ';
  139. q++;
  140. }
  141. else if (*p == '+' || *p == '-' || *p == '*' || *p == '/') {// 如果当前位置是运算符
  142. int priority1 = getPriority(*p);// 获取当前运算符的优先级
  143. while (!isEmpty(&s) && isOperator(top(&s)) && getPriority(top(&s)) >= priority1) {
  144. // 如果栈不空,栈顶为运算符,并且栈顶运算符的优先级大于等于当前运算符的优先级
  145. char op = pop(&s);// 将栈顶运算符弹出
  146. *q = op;// 将弹出的运算符输出到后缀表达式中
  147. q++;
  148. *q = ' ';// 输出空格
  149. q++;
  150. }
  151. push(&s, *p);// 将当前运算符入栈
  152. p++;
  153. }
  154. else if (*p == '(') {// 如果当前位置是左括号
  155. push(&s, *p);// 将其入栈
  156. p++;
  157. }
  158. else if (*p == ')') {// 如果当前位置是右括号
  159. while (!isEmpty(&s) && top(&s) != '(') {// 不断将栈中的元素弹出,直到遇到左括号
  160. char op = pop(&s);
  161. *q = op;// 将弹出的运算符输出到后缀表达式中
  162. q++;
  163. *q = ' ';// 输出空格
  164. q++;
  165. }
  166. if (!isEmpty(&s) && top(&s) == '(') {// 如果栈不空且栈顶元素是左括号
  167. pop(&s);// 将左括号弹出并丢弃
  168. }
  169. else {
  170. printf("Invalid expression: %s\n", infix);// 若遍历完中缀表达式后栈中仍然有元素,或遇到错误情况,则输出错误信息
  171. exit(1);
  172. }
  173. p++;
  174. }
  175. else {// 如果当前位置不是数字、运算符、左括号或右括号,直接跳过
  176. p++;
  177. }
  178. }
  179. while (!isEmpty(&s)) {// 如果栈不空,则将栈中所有元素弹出并输出到后缀表达式中
  180. char op = pop(&s);
  181. *q = op;
  182. q++;
  183. *q = ' ';// 输出空格
  184. q++;
  185. }
  186. *(q - 1) = '\0';// 给后缀表达式添加结束符
  187. }
  188. int main() {
  189. char infix[100];
  190. char postfix[100];
  191. printf("Enter an infix expression: ");
  192. scanf("%s", infix);
  193. infixToPostfix(infix, postfix);// 将中缀表达式转为后缀表达式
  194. printf("Postfix notation: %s\n", postfix);
  195. double result = evaluate(postfix);// 计算后缀表达式的值
  196. printf("Result: %g\n", result);
  197. return 0;
  198. }

测试结果: 

更新测试代码: 支持负数运算

  1. #define _CRT_SECURE_NO_WARNINGS 1
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <ctype.h>
  5. typedef struct {
  6. double* data; // 存储栈数据的数组指针
  7. int top; // 栈顶指针
  8. int size; // 栈的大小
  9. } Stack;
  10. // 初始化栈
  11. void initStack(Stack* s, int size) {
  12. s->data = (double*)malloc(sizeof(double) * size); // 动态分配内存
  13. s->top = -1; // 初始化栈顶指针
  14. s->size = size; // 设置栈的大小
  15. }
  16. // 判断栈是否为空
  17. int isEmpty(Stack* s) {
  18. return s->top == -1; // 栈顶指针为-1时,栈为空
  19. }
  20. // 判断栈是否已满
  21. int isFull(Stack* s) {
  22. return s->top == s->size - 1; // 栈顶指针等于栈的大小减1时,栈已满
  23. }
  24. // 入栈操作
  25. void push(Stack* s, double value) {
  26. if (isFull(s)) {
  27. printf("Stack overflow\n");
  28. exit(1); // 栈满时退出程序
  29. }
  30. s->top++; // 栈顶指针增加
  31. s->data[s->top] = value; // 将值放入栈顶
  32. }
  33. // 出栈操作
  34. double pop(Stack* s) {
  35. if (isEmpty(s)) {
  36. printf("Stack underflow\n");
  37. exit(1); // 栈空时退出程序
  38. }
  39. double value = s->data[s->top]; // 取栈顶元素
  40. s->top--; // 栈顶指针减少
  41. return value; // 返回栈顶元素
  42. }
  43. // 获取栈顶元素
  44. double top(Stack* s) {
  45. if (isEmpty(s)) {
  46. printf("Stack underflow\n");
  47. exit(1); // 栈空时退出程序
  48. }
  49. return s->data[s->top]; // 返回栈顶元素
  50. }
  51. // 判断字符是否是运算符
  52. int isOperator(char c) {
  53. return c == '+' || c == '-' || c == '*' || c == '/';
  54. }
  55. // 获取运算符优先级
  56. int getPriority(char op) {
  57. switch (op) {
  58. case '+':
  59. case '-':
  60. return 1;
  61. case '*':
  62. case '/':
  63. return 2;
  64. default:
  65. return 0;
  66. }
  67. }
  68. // 执行四则运算
  69. double operate(double num1, double num2, char op) {
  70. switch (op) {
  71. case '+':
  72. return num1 + num2;
  73. case '-':
  74. return num1 - num2;
  75. case '*':
  76. return num1 * num2;
  77. case '/':
  78. return num1 / num2;
  79. default:
  80. printf("Invalid operator: %c\n", op);
  81. exit(1); // 遇到无效运算符时退出程序
  82. }
  83. }
  84. // 判断是否是负号
  85. int isNegativeSign(char* p, char* infix) {
  86. if (*p != '-') return 0; // 如果不是减号,则返回0
  87. if (p == infix) return 1; // 如果是表达式的开始,则是负号
  88. // 如果前一个字符是左括号或其他运算符,则当前的减号是负号
  89. return (*(p - 1) == '(') || isOperator(*(p - 1));
  90. }
  91. // 将中缀表达式转换为后缀表达式
  92. void infixToPostfix(char* infix, char* postfix) {
  93. Stack s;
  94. initStack(&s, 100); // 初始化栈
  95. char* p = infix;
  96. char* q = postfix;
  97. while (*p != '\0') {
  98. if (isdigit(*p)) { // 如果是数字
  99. do {
  100. *q++ = *p++;
  101. } while (isdigit(*p) || *p == '.');
  102. *q++ = ' ';
  103. } else if (isOperator(*p)) {
  104. if (*p == '-' && isNegativeSign(p, infix)) {
  105. *q++ = '0'; // 补零以处理负号
  106. *q++ = ' ';
  107. }
  108. while (!isEmpty(&s) && isOperator(top(&s)) &&
  109. getPriority(top(&s)) >= getPriority(*p)) {
  110. *q++ = pop(&s);
  111. *q++ = ' ';
  112. }
  113. push(&s, *p);
  114. p++;
  115. } else if (*p == '(') {
  116. push(&s, *p); // 处理左括号
  117. p++;
  118. } else if (*p == ')') {
  119. while (!isEmpty(&s) && top(&s) != '(') {
  120. *q++ = pop(&s); // 处理右括号
  121. *q++ = ' ';
  122. }
  123. if (!isEmpty(&s)) {
  124. pop(&s); // 弹出左括号
  125. }
  126. p++;
  127. } else {
  128. p++; // 跳过空格
  129. }
  130. }
  131. while (!isEmpty(&s)) { // 将栈中剩余的运算符加入后缀表达式
  132. *q++ = pop(&s);
  133. *q++ = ' ';
  134. }
  135. *q = '\0'; // 结束后缀表达式
  136. }
  137. // 计算后缀表达式的值
  138. double evaluate(char* postfix) {
  139. Stack s;
  140. initStack(&s, 100); // 初始化栈
  141. char* p = postfix;
  142. while (*p != '\0') {
  143. if (isdigit(*p)) { // 如果是数字
  144. double num = 0.0;
  145. while (isdigit(*p)) { // 提取整数部分
  146. num = num * 10 + (*p - '0');
  147. p++;
  148. }
  149. if (*p == '.') { // 提取小数部分
  150. double frac = 0.1;
  151. p++;
  152. while (isdigit(*p)) {
  153. num += (*p - '0') * frac;
  154. frac /= 10;
  155. p++;
  156. }
  157. }
  158. push(&s, num);
  159. } else if (*p == ' ') {
  160. p++;
  161. } else if (isOperator(*p)) { // 如果是运算符
  162. double num2 = pop(&s);
  163. double num1 = pop(&s);
  164. double result = operate(num1, num2, *p);
  165. push(&s, result);
  166. p++;
  167. }
  168. }
  169. return pop(&s); // 返回计算结果
  170. }
  171. int main() {
  172. char infix[100];
  173. char postfix[100];
  174. printf("Enter an infix expression: ");
  175. scanf("%s", infix); // 读取中缀表达式
  176. infixToPostfix(infix, postfix); // 将中缀表达式转换为后缀表达式
  177. printf("Postfix notation: %s\n", postfix); // 打印后缀表达式
  178. double result = evaluate(postfix); // 计算后缀表达式的结果
  179. printf("Result: %g\n", result); // 打印结果
  180. return 0;
  181. }

 测试截图:

参考:

  1. 石田保辉:《我的第一本算法书》
  2. 渡部有隆:《挑战程序设计竞赛2》
  3. 程杰:《大话数据结构》
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/616761
推荐阅读
相关标签
  

闽ICP备14008679号