CMakeLists.txt

This commit is contained in:
2026-07-31 00:33:17 +08:00
parent f853068f9b
commit 32d7529967
8 changed files with 396 additions and 71 deletions
+97
View File
@@ -0,0 +1,97 @@
#include <iostream>
#include <string>
#include <optional>
#include <vector>
#include <variant>
#include <memory>
#include <tuple>
#include <stdexcept>
#include <sstream>
#include <cstdio>
using namespace std;
class NotationTree {
public:
using Data = variant<double, char>;
struct TreeNode {
Data data;
optional<size_t> left_idx, right_idx;
explicit TreeNode(const string& value) { data = parse_string(value); }
explicit TreeNode(const Data value) { data = value; }
[[nodiscard]] bool is_operator() const {
return std::holds_alternative<char>(data);
}
[[nodiscard]] char get_operator() const {
if (!is_operator()) { throw invalid_argument("Node is not operator"); }
return get<char>(data);
}
[[nodiscard]] double get_number() const {
if (is_operator()) { throw invalid_argument("Node is operator"); }
return get<double>(data);
}
};
static Data parse_string(const string& value) {
if (value == "+" || value == "-" || value == "*" || value == "/") {
return value[0];
}
return stod(value);
}
vector<TreeNode> nodes;
tuple<size_t, size_t> build_from_poland(const vector<Data>& datas, const size_t start_idx = 0) {
size_t this_idx = nodes.size();
nodes.emplace_back(datas[start_idx]);
if (!nodes.back().is_operator()) { return make_tuple(this_idx, start_idx + 1); }
auto [left_idx, right_start_idx] = build_from_poland(datas, start_idx + 1);
nodes[this_idx].left_idx = left_idx;
auto [right_idx, right_end_idx] = build_from_poland(datas, right_start_idx);
nodes[this_idx].right_idx = right_idx;
return make_tuple(this_idx, right_end_idx);
}
double calculate(const size_t idx = 0) {
if (!nodes[idx].is_operator()) {
return nodes[idx].get_number();
}
if (!nodes[idx].left_idx.has_value() || !nodes[idx].right_idx.has_value()) {
throw invalid_argument("Tree is not complete");
}
const double left_result = calculate(nodes[idx].left_idx.value()),
right_result = calculate(nodes[idx].right_idx.value());
switch (nodes[idx].get_operator()) {
case '+': return left_result + right_result;
case '-': return left_result - right_result;
case '*': return left_result * right_result;
case '/': return left_result / right_result;
default: throw invalid_argument("Invalid operator");
}
}
};
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
string poland_notation, token;
vector<NotationTree::Data> datas;
getline(cin, poland_notation);
stringstream ss(poland_notation);
while (ss >> token) {
datas.push_back(NotationTree::parse_string(token));
}
NotationTree tree;
tree.build_from_poland(datas);
printf("%f\n", tree.calculate());
return 0;
}