C++逆波兰计算表达式

  1 //逆波兰数实现表达式运算
  2 #include<iostream>
  3 #include<string>
  4 #include<stdlib.h>
  5 using namespace std;
  6 
  7 //链栈
  8 template<class T>
  9 struct LinkStack {
 10     T num;
 11     struct LinkStack* next;
 12 };
 13 
 14 template<class T>
 15 void InitStack(LinkStack<T>*& L) {
 16     L = (LinkStack<T>*)malloc(sizeof(LinkStack<T>));
 17     L->next = NULL;
 18 }
 19 
 20 template<class T>
 21 void Push(LinkStack<T>*& L, T e) {
 22     LinkStack<T>* p = (LinkStack<T>*)malloc(sizeof(LinkStack<T>));
 23     p->num = e;
 24     p->next = L->next;//头插法入栈
 25     L->next = p;
 26 }
 27 
 28 template<class T>
 29 void Pop(LinkStack<T>*& L, T& x) {
 30     LinkStack<T>* p = L->next;
 31     x = p->num;
 32     L->next = p->next;
 33     delete p;
 34 }
 35 
 36 template<class T>
 37 bool isEmpty(LinkStack<T>* L) {
 38     return L->next == NULL;
 39 }
 40 
 41 template<class T>
 42 char getTop(LinkStack<T>* L) {
 43     if(L->next !=NULL)return L->next->num;//?
 44 
 45 }
 46 
 47 void calcu(LinkStack<int> *&nums,LinkStack<char> *&opech) {
 48     int left, right, result;
 49     char oper;
 50     Pop(nums, right);
 51     Pop(nums, left);
 52     Pop(opech, oper);
 53     if (oper == '+')result = left + right;
 54     if (oper == '-')result = left - right;
 55     if (oper == '*')result = left * right;
 56     if (oper == '/')result = left / right;
 57     Push(nums, result);
 58 }
 59 //逆波兰算法实现
 60 int Polish(const char s[], int len) {
 61     LinkStack<int> *nums;
 62     LinkStack<char> *opech;
 63     InitStack(nums); InitStack(opech);
 64     int count = 0;
 65     while (!isEmpty(opech) || count < len) {
 66         //两种情况:当字符串扫描完时,不能使用s[count]
 67         if (count < len) {
 68             //扫描字符串,若为数字压入数字栈,若为运算符压入不确定执行顺序的运算符栈
 69             if (s[count] >= '0' && s[count] <= '9') {//字符串转数字atoi
 70                 int number = s[count++] - '0';
 71                 Push(nums, number);//函数声明里栈是指针传递
 72             }
 73             else {
 74                 //若当前扫描到的运算符优先级大于栈首运算符优先级,则压入栈中,否则弹出栈中所有>=当前字符优先级的字符
 75                 //若遇到),则将直到(的所有运算符依次出栈
 76                 if (s[count] == '(' || getTop(opech) == '(' || isEmpty(opech)) {//所有直接入栈的情况
 77                     Push(opech, s[count++]);
 78                 }
 79                 else if (s[count] == '+' || s[count] == '-') {//可弹出+-*/,或者什么都不谈直接入展
 80                     while (getTop(opech) != '(' && !isEmpty(opech)) {//排除栈空情况
 81                         calcu(nums, opech);
 82                     }
 83                     Push(opech, s[count++]);//栈为空
 84                 }
 85                 else if (s[count] == '*' || s[count] == '/') {
 86                     //禁止使用while(!= || !=)有歧义,只要为+就非-,满足条件,
 87                     while (getTop(opech) == '*' || getTop(opech) == '/') {//只能弹出*/,不需要判空
 88                         calcu(nums, opech);
 89                     }
 90                     Push(opech, s[count++]);
 91                 }
 92                 else if (s[count] == ')') {
 93                     while (getTop(opech) != '(') {//当栈为空时也满足不等于的条件
 94                         if (isEmpty(opech))break;
 95                         calcu(nums, opech);
 96                     }
 97                     char non;
 98                     Pop(opech, non);
 99                     count++;
100                 }
101             }
102         }
103         else {//字符串扫描完,只需对还未空的运算符栈操作
104             calcu(nums, opech);
105         }
106     }
107     return nums->next->num;
108 }
109 int main() {
110     const char* s="3+(4+6)/2-2*(3+3)";
111     int len = strlen(s);
112     int result = Polish(s, len);
113     cout << "result is" << result << endl;
114 }

 

posted @ 2021-03-12 14:06  caseyz)  阅读(487)  评论(0)    收藏  举报