Hm3
This commit is contained in:
146
Exercise/Homework3/表达式树模板.cpp
Normal file
146
Exercise/Homework3/表达式树模板.cpp
Normal file
@@ -0,0 +1,146 @@
|
||||
#include <bits/stdc++.h>
|
||||
using namespace std;
|
||||
|
||||
struct Node {
|
||||
char sign; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҷ<EFBFBD>ӽڵ<D3BD>Ϊ '?'
|
||||
long long num; // <20><><EFBFBD><EFBFBD>
|
||||
Node* left;
|
||||
Node* right;
|
||||
|
||||
Node(): sign('?'), num(-1), left(nullptr), right(nullptr) {}
|
||||
Node(char s): sign(s), num(-1), left(nullptr), right(nullptr) {}
|
||||
Node(long long n): sign('?'), num(n), left(nullptr), right(nullptr) {}
|
||||
};
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD><DDA3><EFBFBD><EFBFBD><EFBFBD>
|
||||
long long fastpow(long long base, long long exp){
|
||||
long long res = 1;
|
||||
while(exp > 0){
|
||||
if(exp & 1) res *= base;
|
||||
base *= base;
|
||||
exp >>= 1;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȼ<EFBFBD>
|
||||
int level(char c){
|
||||
switch(c){
|
||||
case '+': case '-': return 1;
|
||||
case '*': case '/': return 2;
|
||||
case '^': return 3;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// <20>ҵ<EFBFBD><D2B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȼ<EFBFBD><C8BC><EFBFBD><EFBFBD>͵<EFBFBD><CDB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
int findexp(const string &s, int l, int r){
|
||||
int pos = -1;
|
||||
int minLevel = 114514;
|
||||
int balance = 0; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
for(int i = r; i >= l; --i){ // <20>ҽ<EFBFBD><D2BD>ϣ<EFBFBD><CFA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ұ<EFBFBD>
|
||||
if(s[i] == ')') balance++;
|
||||
else if(s[i] == '(') balance--;
|
||||
else if(balance == 0 && level(s[i]) > 0){
|
||||
if(level(s[i]) <= minLevel){
|
||||
minLevel = level(s[i]);
|
||||
pos = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
// <20>ַ<EFBFBD><D6B7><EFBFBD>ת<EFBFBD><D7AA><EFBFBD><EFBFBD>
|
||||
long long toNum(const string &s, int l, int r){
|
||||
long long tmp = 0;
|
||||
while(l <= r && isspace((unsigned char)s[l])) l++;
|
||||
while(r >= l && isspace((unsigned char)s[r])) r--;
|
||||
if(l > r) return 0;
|
||||
for(int i = l; i <= r; ++i){
|
||||
if(!isdigit(s[i])) return 0;
|
||||
tmp = tmp * 10 + (s[i] - '0');
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
class Expression {
|
||||
public:
|
||||
string exp;
|
||||
Node* root;
|
||||
long long result;
|
||||
bool isValid;
|
||||
|
||||
Expression(const string &s): exp(s), root(nullptr), result(0), isValid(true) {}
|
||||
|
||||
Node* build(const string &s, int l, int r){
|
||||
while(l <= r && s[l] == ' ') l++;
|
||||
while(l <= r && s[r] == ' ') r--;
|
||||
if(l > r) return nullptr;
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŵ<EFBFBD><C5B4><EFBFBD>
|
||||
if(s[l] == '(' && s[r] == ')'){
|
||||
int balance = 0;
|
||||
bool hasOuter = true;
|
||||
for(int i = l; i <= r; ++i){
|
||||
if(s[i] == '(') balance++;
|
||||
else if(s[i] == ')') balance--;
|
||||
if(balance == 0 && i < r){
|
||||
hasOuter = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(hasOuter) return build(s, l+1, r-1);
|
||||
}
|
||||
|
||||
int pos = findexp(s, l, r);
|
||||
if(pos == -1){
|
||||
long long val = toNum(s, l, r);
|
||||
return new Node(val);
|
||||
}
|
||||
|
||||
Node* tmp = new Node(s[pos]);
|
||||
tmp->left = build(s, l, pos-1);
|
||||
tmp->right = build(s, pos+1, r);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
long long calc(Node* r, bool &v){
|
||||
if(!r) return 0;
|
||||
if(r->sign == '?') return r->num;
|
||||
|
||||
long long left = calc(r->left, v);
|
||||
long long right = calc(r->right, v);
|
||||
|
||||
switch(r->sign){
|
||||
case '+': return left + right;
|
||||
case '-': return left - right;
|
||||
case '*': return left * right;
|
||||
case '/':
|
||||
if(right == 0){ v = false; return 0; }
|
||||
return left / right;
|
||||
case '^':
|
||||
if(right < 0){ v = false; return 0; }
|
||||
return fastpow(left, right);
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void calc(){
|
||||
isValid = true;
|
||||
result = calc(root, isValid);
|
||||
}
|
||||
};
|
||||
|
||||
int main(){
|
||||
string s;
|
||||
while(getline(cin, s)){
|
||||
Expression tree(s);
|
||||
tree.root = tree.build(s, 0, s.length()-1);
|
||||
tree.calc();
|
||||
if(tree.isValid) cout << tree.result << endl;
|
||||
else cout << "INVALID" << endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user