数据结构与算法——栈 表达式求值
给定一个只包含加减乘除法运算的算术表达式,编写一套算法来计算表达式的值。
输入格式
输入一行,为需要你计算的表达式,表达式中只包含数字、加法运算符“+”、 减法运算符 “-”、乘法运算符“*”和 除 法运算符“/”,且没有括号,不考虑数值的范围(溢出),待求解的表达式以“=”号结束。
如: 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