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

215 lines
4.4 KiB
C++
Raw 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])) {
// 对于右结合的^,使用<而不是<=
if ((s[i] == '^' && level(s[i]) < min_level) ||
(s[i] != '^' && level(s[i]) <= min_level)) {
min_level = level(s[i]);
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;
}
/*
带符号的版本
long long toNum(const string& s, int l, int r){
long long tmp = 0;
bool neg = false;
if (s[l] == '-') { neg = true; l++; }
for(int i = l; i <= r; i++){
if(isdigit(s[i])) tmp = tmp * 10 + (s[i] - '0');
}
return neg ? -tmp : 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);
//cout << "*" << r << endl; 为什么输出0
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 '^': {
if(left == 0 && right == 0) { isValid = false; return 0; }
return fastpow(left, right);
break;
}
default: return 0;
}
}
}
void print(){
inorder(root);
}
};
int main(){
/*
string s;
getline(cin, s);
Expression tree(s);
tree.root = tree.build(s, 0, s.length() - 1);
//tree.print();
cout << tree.calc(tree.root, tree.isValid) << endl;
//if(!tree.isValid && result != -1) cout << result <<endl;
//else cout << "Invalid" << endl; */
string s;
while(getline(cin, s)){
Expression tree(s);
tree.root = tree.build(s, 0, s.length()-1);
long long result = tree.calc(tree.root, tree.isValid);
if(tree.isValid) cout << result << endl;
else cout << "INVALID" << endl;
}
return 0;
}