Fork me on GitHub

数据结构与算法——栈 表达式求值

给定一个只包含加减乘除法运算的算术表达式,编写一套算法来计算表达式的值。

 

输入格式

输入一行,为需要你计算的表达式,表达式中只包含数字、加法运算符“+”、 减法运算符 “-”、乘法运算符“*”和 除 法运算符“/”,且没有括号,不考虑数值的范围(溢出),待求解的表达式以“=”号结束。

如: 12 + 3*6/3 + 4*5 =

 

完整源码实现:

expression.h

 1 #pragma once
 2 #include<stdio.h>
 3 #include<stdlib.h>
 4 
 5 #define MAXSIZE 100                         //预先分配空间,这个数值根据实际需要预估确定
 6 
 7 typedef int ElemType;
 8 
 9 //栈指针 struct
10 typedef struct _SqStack
11 {
12     ElemType* base;                         //栈底指针
13     ElemType* top;                          //栈顶指针
14 }SqStack;
15 
16 //初始化 构造一个空栈
17 bool InitStack(SqStack& S)                  
18 {
19     S.base = new ElemType[MAXSIZE];         //为顺序栈分配一个最大容量为 Maxsize 的空间
20     if (!S.base)                            //空间分配失败
21         return false;
22     S.top = S.base;                         //top 初始为 base,空栈
23     return true;
24 }
25 
26 // 插入元素 e 为新的栈顶元素
27 bool PushStack(SqStack& S, ElemType e)
28 {
29     if (S.top - S.base == MAXSIZE)          //判断是否栈满
30         return false;
31     *(S.top++) = e;                         //元素 e 压入栈顶,然后栈顶指针加 1,等价于*S.top=e; S.top++;
32      
33     return true;
34 }
35 
36 //删除 S 的栈顶元素,暂存在变量 e中
37 bool PopStack(SqStack& S, ElemType& e)    
38 {
39     if (S.base == S.top)                    //栈空
40     {
41         return false;
42     }
43     e = *(--S.top);                         //栈顶指针减 1,将栈顶元素赋给 e
44 
45     return true;
46 }
47 
48 //返回 S 的栈顶元素,栈顶指针不变
49 ElemType* GetTop(SqStack& S)
50 {
51     if (S.top != S.base)                    //栈非空
52     {
53         return S.top - 1;                   //返回栈顶元素的值,栈顶指针不变
54     }
55     else
56     {
57         return NULL;
58     }
59 }
60 
61 //返回栈中元素个数
62 int GetSize(SqStack& S)
63 {
64     return (S.top - S.base);
65 }
66 
67 //判断栈是否为空 为空返回Ture 不为空返回False
68 bool IsEmpty(SqStack& S)
69 {
70     if (S.top == S.base)
71     {
72         return true;
73     }
74     else
75     {
76         return false;
77     }
78 }
79 
80 //销毁栈
81 void DestoryStack(SqStack& S)
82 {
83     if (S.base)
84     {
85         free(S.base);
86         S.base = NULL;
87         S.top = NULL;
88     }
89 }

 

 

 

expression.cpp

  1 #include <stdio.h>
  2 #include <iostream>
  3 #include "expression.h"
  4 
  5 using namespace std;
  6 
  7 //lhs(当前运算符)与rhs(栈顶)的运算符比较 ,对比优先级,如果 lhs 优先级高,则返回 Ture
  8 bool isLarger(const int& lhs, const int& rhs)
  9 {
 10     if ((rhs == '+' || rhs == '-') && (lhs == '*' || lhs == '/'))
 11     {
 12         return true;
 13     }
 14     return false;
 15 }
 16 
 17 //对运算符求值 (int left, int right, int op)  
 18 int operate(int left, int right, int op)        
 19 {
 20     int result = 0;
 21     cout << "left:" << left << "  right:" << right << "  op:" << (char)op << endl;
 22 
 23     switch (op)
 24     {
 25     case '+':
 26         result = left + right;
 27         break;
 28     case '-':
 29         result = left - right;
 30         break;
 31     case '*':
 32         result = left * right;
 33         break;
 34     case '/':
 35         result = left / right;
 36         break;
 37     default:
 38         break;
 39     }
 40     cout << "result: " << result << endl;
 41     return result;
 42 }
 43 
 44 //计算方法
 45 int calculate(string input)
 46 {
 47     SqStack data_stack;                 //操作数堆栈
 48     SqStack opt_stack;                  //运算符堆栈
 49     int status = 0;                     //0_接受左操作数   |   1_接受运算符 "+ - * /"   |   2_接受右操作数
 50     int ldata = 0;                      //左操作数
 51     int rdata = 0;                      //右操作数
 52     //char last_opt = '\0';
 53 
 54     //初始化栈:操作数和操作符
 55     InitStack(data_stack);
 56     InitStack(opt_stack);
 57 
 58     for (int i = 0; i < input.length(); i++)
 59     {
 60         if (isspace(input[i])) continue;                        //isspace 方法,如果是空白字符将会返回1,可以忽略掉空格键等
 61         switch (status)
 62         {
 63             case 0:                                             //case 0 的作用为取字符串中的十进制数字
 64             if (isdigit(input[i]))                              //isdigit 方法,用于检查是否是10进制数,若参数为0~9,则返回ture,否则返回false
 65             {
 66                 ldata *= 10;                                    //如果有参数则十进位
 67                 ldata += input[i] - '0';                        //由数字符的ASCII码减去0的ASCII码将会得到int型的对应数字
 68                 printf("\n");
 69             }
 70             else
 71             {
 72                 cout << "得到左操作数:" << ldata << endl;       //运行到这里说明这一段的整数获取完毕
 73                 PushStack(data_stack, ldata);                   //左操作数入栈
 74                 i--;                                            //退回到这个非数字前的下标,让他从 case 1 处入栈
 75                 status = 1;                                     //数字后要跟运算符,准备进入 case 1
 76                 printf("\n");
 77             }
 78             break;
 79 
 80             case 1:
 81             if (input[i] == '+' || input[i] == '-' || input[i] == '*' || input[i] == '/')
 82             {
 83                 //第一个运算符,暂时不做任何处理,运算符先入栈保存
 84                 if(IsEmpty(opt_stack))                                 
 85                 {
 86                     cout << "运算符栈为空" << endl;
 87                     PushStack(opt_stack, input[i]);                         //操作符入栈
 88                     cout << "运算符“" << input[i] << "”入栈" << endl;
 89                     status = 2;
 90                     printf("\n");
 91                 }
 92                 else
 93                 {   //非第一个运算符,则与之前的运算符比较优先级
 94                     cout << "" << (char)(*GetTop(opt_stack)) << "”与“" << input[i] << "”对比优先级" <<endl;
 95                     
 96                     //input[i](当前运算符) 与 *GetTop(opt_stack)(栈顶)的运算符比较 ,对比优先级,如果 input[i] 优先级高,则返回 Ture
 97                     if (isLarger(input[i], *GetTop(opt_stack)))
 98                     {
 99                         cout << "运算符 “" << input[i] <<"”优先级更高"<< endl;
100                         PushStack(opt_stack, input[i]);                                 //操作符入栈
101                         cout << "运算符 “" << input[i] << "”入栈" << endl;
102                         status = 2;                                                     //准备获取运算符右侧的操作数
103                         rdata = 0;
104                         printf("\n");
105                     }
106                     else
107                     {   //当前运算符的优先级不高于前一个运算符,则计算前一个运算符的值
108                         int left = 0, right = 0;
109                         int opt;
110                         cout << "运算符 “" << (char)*GetTop(opt_stack) << "”优先级更高" << endl;
111                         do
112                         {
113                             PopStack(data_stack, right);            //清除数字栈顶元素,放到右值
114                             PopStack(data_stack, left);             //清除数字栈顶元素,放到左值
115                             PopStack(opt_stack, opt);               //清除运算符栈顶元素,参与运算(之所以要拿栈中的,是因为相同优先算左边)
116                             cout << "运算符“" << (char)opt << "”出栈,准备参与运算" << endl;
117                             int result = operate(left, right, opt);
118                             PushStack(data_stack, result);          //将优先计算所得的计算结果放入数字栈
119                             printf("\n");
120                         }
121                         //如果符号栈中还有符号,并且栈中这个运算符优先级高,则继续循环
122                         while (!IsEmpty(opt_stack) && !isLarger(input[i], *GetTop(opt_stack)));
123                         //如果符号栈中没有运算符,或栈中运算符优先级并不高,则跳出上方do while循环,将低优先级运算符压栈
124                         PushStack(opt_stack, input[i]);
125                         cout << "运算符“" << (char)input[i] << "”入栈" << endl;
126 
127                         status = 2;                                 //继续获取右操作数
128                         rdata = 0;
129                         printf("\n");
130                     }
131                 }
132             }
133             else if (input[i] == '=')               //运行到此处,说明“=”运算符前方优先运算的内容均运算完毕,只剩“+ -”低级运算
134             {   //计算结果
135                 int opt, result;
136                 do
137                 {
138                     PopStack(data_stack, rdata);
139                     PopStack(data_stack, ldata);
140                     PopStack(opt_stack, opt);
141                     result = operate(ldata, rdata, opt);
142                     PushStack(data_stack, result);
143                 } while (!IsEmpty(opt_stack));          //将栈中剩余元素相加减
144 
145                 return result;
146             }
147             else
148             {
149                 cerr << "输入运算符错误!" << endl;
150             }
151             break;
152 
153             case 2:
154             if (isdigit(input[i]))                  //isdigit方法,用于检查是否是10进制数,若参数为0~9,则返回ture,否则返回false
155             {
156                 rdata *= 10;                        //与 case 1 处获取左值一样,从字符串中获取整型十进制数的方法
157                 rdata += input[i] - '0';            //由数字符的ASCII码减去0的ASCII码将会得到int型的对应数字
158             }
159             else
160             {
161                 cout << "得到右操作数:" << rdata << endl;           //进入到这里说明右操作数获取完毕,isdigit(input[i])拿到了一个运算符
162                 PushStack(data_stack, rdata);                       //右操作数入栈
163                 i--;                                                //退回到这个非数字前的下标
164                 status = 1;                                         //右操作数字后要跟运算符,准备进入 case 1
165                 printf("\n");
166             }
167             break;
168         }
169     }
170     return -1;                                              //最后的结果为栈顶元素
171 }
172 
173 int main(int argc, char const* argv[])
174 {
175     string str = "12+3*6/3+4*5=";
176     cout << calculate(str) << endl;
177     system("pause");
178     return 0;
179 }

 

 

 

 

520

posted @ 2020-11-01 23:22  索智源  阅读(549)  评论(0编辑  收藏  举报