数据结构课程实验题目,很长的模板类…值得去存一下。
主要实现原理:
后缀表达式又成为逆波兰表达式,在sicp里面有讲过,简单的加减乘除可以用栈很快写出来,但是要用到括号,幂运算等就要整理出符号的优先级,根据优先级的比较决定是否进行入栈。
ps.先占个坑
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <string>
#include <cstring>
#include <stack>
#include<stdlib.h>
#include <vector>
#include <sstream>
//#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair <int,int> pii;
#define mem(s,t) memset(s,t,sizeof(s))
#define D(v) cout<<#v<<" "<<v<<endl
#define inf 0x3f3f3f3f
#define pb push_back
//#define LOCAL
const int MAXN =1e5+10;
template<typename T>
class postfixEval {
public:
postfixEval();
string getPostfixExp() const;
void setPostfixExp(const string& postfixExp);
T evaluate();
stack<T> operandStack;
private:
string postfixExpression;
void getOperands(T& left, T& right);
T compute(T left, T right, char op) const;
bool isOperator(char ch) const;
// is ch one of '+','-','*','/','%','^'
};
template<typename T>
void postfixEval<T>::getOperands(T& left, T& right) {
if (operandStack.empty())
throw "postfixEval: Too many operators";
right = operandStack.top();
operandStack.pop();
if (operandStack.empty())
throw "postfixEval: Too many operators";
left = operandStack.top();
operandStack.pop();
}
template<typename T>
T postfixEval<T>::compute(T left, T right, char op) const {
T value;
switch(op) {
case '+':
value = left + right;
break;
case '-':
value = left - right;
break;
case '*':
value = left * right;
break;
case '%':
if(int(right)!=right) throw "invalid expression";
if (right == 0) throw "postfixEval: divide by 0";
value = int(left) % int(right)*1.0;
break;
case '/':
if (right == 0)
throw "postfixEval: divide by 0";
value = left / right;
break;
case '^':
if (left == 0 && right == 0)
throw "postfixEval: 0^0 undefined";
value = 1;
while (right > 0) {
value *= left;
right--;
}
break;
}
return value;
}
template<typename T>
bool postfixEval<T>::isOperator(char ch) const {
return ch == '+' || ch == '-' || ch == '*' ||
ch == '%' || ch == '/' || ch == '^';
}
template<typename T>
postfixEval<T>::postfixEval() {}
template<typename T>
string postfixEval<T>::getPostfixExp() const {
return postfixExpression;
}
template<typename T>
void postfixEval<T>::setPostfixExp(const string& postfixExp) {
postfixExpression = postfixExp;
}
template<typename T>
T postfixEval<T>::evaluate() {
T left, right, expValue;
char ch;
int cnt=0;
int id[MAXN];
string temp(postfixExpression);
for(int i=0; i<temp.size(); i++) {
if(isOperator(temp[i])) {
temp[i]=' ';
id[cnt++]=i;
}
}
stringstream ss(temp);
T x;
vector<T> vec;
while(ss>>x) {
vec.pb(x);
}
for (int i=0,j=0,x=0; i < postfixExpression.length();) {
while(isspace(postfixExpression[i])) i++;
char ch=postfixExpression[i];
if(id[j]==i) {
getOperands(left, right);
operandStack.push(compute(left, right, ch));
i++;
j++;
} else {
operandStack.push(vec[x++]);
while(!isspace(temp[i])) i++;
}
}
expValue = operandStack.top();
operandStack.pop();
if (!operandStack.empty())
throw "postfixEval: Too many operands";
return expValue;
}
class expressionSymbol {
public:
expressionSymbol();
expressionSymbol(char ch);
friend bool operator>= (const expressionSymbol& left,
const expressionSymbol& right);
char getOp() const;
private:
char op;
int inputPrecedence;
int stackPrecedence;
};
expressionSymbol::expressionSymbol() {}
expressionSymbol::expressionSymbol(char ch) {
op = ch;
switch(op) {
case '+':
case '-':
inputPrecedence = 1;
stackPrecedence = 1;
break;
case '*':
case '%':
case '/':
inputPrecedence = 2;
stackPrecedence = 2;
break;
case '^':
inputPrecedence = 4;
stackPrecedence = 3;
break;
case '(':
inputPrecedence = 5;
stackPrecedence = -1;
break;
case ')':
inputPrecedence = 0;
stackPrecedence = 0;
break;
}
}
char expressionSymbol::getOp() const {
return op;
}
bool operator>= (const expressionSymbol& left, const expressionSymbol& right ) {
return left.stackPrecedence >= right.inputPrecedence;
}
class infix2Postfix {
public:
infix2Postfix();
infix2Postfix(const string& infixExp);
void setInfixExp(const string& infixExp);
string postfix();
private:
string infixExpression;
string postfixExpression;
stack<expressionSymbol> operatorStack;
void outputHigherOrEqual(const expressionSymbol& op);
bool isOperator(char ch) const;
// ch is one of '+','-','*','/','%','^'
};
void infix2Postfix::outputHigherOrEqual(const expressionSymbol& op) {
expressionSymbol op2;
while(!operatorStack.empty() &&
(op2 = operatorStack.top()) >= op) {
operatorStack.pop();
postfixExpression += op2.getOp();
postfixExpression += ' ';
}
}
bool infix2Postfix::isOperator(char ch) const {
return ch == '+' || ch == '-' || ch == '*' ||
ch == '%' || ch == '/' || ch == '^';
}
infix2Postfix::infix2Postfix() {
}
infix2Postfix::infix2Postfix(const string& infixExp):
infixExpression(infixExp) {
}
void infix2Postfix::setInfixExp(const string& infixExp) {
infixExpression = infixExp;
postfixExpression = "";
}
string infix2Postfix::postfix() {
expressionSymbol op;
int rank = 0;
char ch;
string temp(infixExpression);
int cnt=0,id[MAXN];
mem(id,0);
for(int i=0; i<temp.size(); i++) {
if(isOperator(temp[i]) || temp[i]=='(' || temp[i]==')') temp[i]=' ',id[cnt++]=i;
}
stringstream ss(temp);
double x;
vector<double> vec;
while(ss>>x) {
vec.pb(x);
}
for (int i=0,j=0,x=0; i < infixExpression.length();) {
ch = infixExpression[i];
if(isspace(ch)) {
i++;
} else {
if (i!=id[j]) {
stringstream s;
string aa;
s<<vec[x++];
s>>aa;
postfixExpression += aa;
while(!isspace(infixExpression[i]) && i<infixExpression.length()) i++;
postfixExpression += ' ';
rank++;
if (rank > 1)
throw "infix2Postfix: Operator expected";
} else {
j++;
if (isOperator(ch) || ch == '(') {
if (ch != '(') rank--;
if (rank < 0)
throw "infix2Postfix: Operand expected";
else {
op = expressionSymbol(ch);
outputHigherOrEqual(op);
operatorStack.push(op);
}
i++;
} else if (ch == ')') {
op = expressionSymbol(ch);
outputHigherOrEqual(op);
if(operatorStack.empty())
throw "infix2Postfix: Missing '('";
else
operatorStack.pop();
i++;
} else if (!isspace(ch)) {
throw "infix2Postfix: Invalid input";
i++;
}
}
}
}
if (rank != 1)
throw "infix2Postfix: Operand expected";
else {
while (!operatorStack.empty()) {
op = operatorStack.top();
operatorStack.pop();
if (op.getOp() == '(')
throw "infix2Postfix: Missing ')'";
else {
postfixExpression += op.getOp();
postfixExpression += ' ';
}
}
}
return postfixExpression;
}
int main() {
//calc postfixExpression 1
postfixEval<double> p1;
p1.setPostfixExp("1 3 + 3 /");
cout<<p1.evaluate()<<endl;
//calc postfixExpression 2
postfixEval<int> p2;
p1.setPostfixExp("2 3 - 3 *");
cout<<p1.evaluate()<<endl;
//infix2Postfix 1
infix2Postfix a;
cout<<"( 2 + 3 ) * 7"<<endl;
a.setInfixExp("( 2 + 3 ) * 7");
cout<<a.postfix()<<endl;
//infix2Postfix 2
infix2Postfix b;
b.setInfixExp("( 2 + 3 ) * ( 7 / 8 )");
cout<<b.postfix()<<endl;
//infix2Postfix 3
infix2Postfix c;
c.setInfixExp("( 2.2 + 3.5 ) * ( 7.1 / 8.5 ) ^ 3");
cout<<c.postfix()<<endl;
return 0;
}