Files
Data-Structure/Exercise/Homework3/Q1过了的版本.cpp
e2hang 218a2fb56a Hm3
2025-10-24 09:52:24 +08:00

195 lines
3.7 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <iostream>
#include <string>
using namespace std;
//辅助
long long fastpow(long long d, long long u){
//d^u用快速幂
long long result = 1, base = d, b = u;
while(b > 0){
if(b & 1) result *= base;
base *= base;
b >>= 1;
}
return result;
}
int level(char c){
switch(c){
case '+':
case '-': {
return 1;
break;
}
case '*':
case '/': {
return 2;
break;
}
case '^': {
return 3;
break;
}
default: {
return 0;
break;
}
}
}
int findexp(const string& s, int l, int r) {
int pos = -1;
int min_level = 114514;
int js = 0;
for (int i = r; i >= l; i--) {
if (s[i] == ')') js--;
else if (s[i] == '(') js++;
if (js == 0 && level(s[i])) {
int lev = level(s[i]);
if (lev < min_level || (lev == min_level && s[i] == '^')) {
min_level = lev;
pos = i;
}
}
}
return pos;
}
long long toNum(const string& s, int l, int r) {
long long tmp = 0;
// 跳过空格
while (l <= r && s[l] == ' ') l++;
while (l <= r && s[r] == ' ') r--;
if (l > r) return 0;
// 从左到右处理数字
for (int i = l; i <= r; i++) {
if (isdigit(s[i])) {
tmp = tmp * 10 + (s[i] - '0');
} else {
return 0; // 非法字符
}
}
return tmp;
}
struct Node{
char sign;
long long num;
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) {}
};
class Expression{
public:
string exp;
Node* root;
long long result;
bool isValid;
Expression(const string& s): exp(s), root(nullptr), result(-1), isValid(true) {}
void inorder(Node* r){
if(!r) return;
inorder(r->left);
if (r->sign == '?') cout << r->num;
else cout << r->sign;
inorder(r->right);
}
Node* build(const string& s, int l, int r){
//[l, r]
//处理空格
while(l <= r && s[l] == ' ') l++;
while(l <= r && s[r] == ' ') r--;
if(l > r) return nullptr;
//处理外部括号
if(s[l] == '(' && s[r] == ')'){
bool hasQuote = true;
int js = 0;
for(int i = l; i <= r; i++){
if(s[i] == '(') js++;
else if(s[i] == ')') js--;
if(js == 0 && i != r){
hasQuote = false;
break;
}
}
if (hasQuote) return build(s, l + 1, r - 1);
}
int pos = findexp(s, l, r);
//处理纯数字
if(pos == -1) {
long long x = toNum(s, l, r);
return new Node(x);
}
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& isValid){
if(!r) return 0;
//数字
if(r->sign == '?') return r->num;
//符号
long long left = calc(r->left, isValid);
long long right = calc(r->right, isValid);
if(r->num == -1){
char c = r->sign;
switch(c){
case '+': return left + right;
case '-': return left - right;
case '*': return left * right;
case '/': {
if(right == 0) {
isValid = false;
return 0;
}
else return left / right;
}
case '^': {
return fastpow(left, right);
}
default: return 0;
}
}
return 0;
}
void print(){
inorder(root);
}
};
int main(){
string s;
while(getline(cin, s)){
if (s.empty()) {
cout << "INVALID" << endl;
continue;
}
Expression tree(s);
tree.root = tree.build(s, 0, s.length()-1);
if (!tree.root) {
cout << "INVALID" << endl;
continue;
}
long long result = tree.calc(tree.root, tree.isValid);
if(tree.isValid) cout << result << endl;
else cout << "INVALID" << endl;
}
return 0;
}