186 lines
5.1 KiB
C++
186 lines
5.1 KiB
C++
#include <iostream>
|
|
#include <stack>
|
|
#include <string>
|
|
#include <cctype>
|
|
#include <map>
|
|
|
|
// 2. pseudo code of the algorithm
|
|
// convert to postfix expression use stack,
|
|
// 1. if it is an operand, add to postfix,
|
|
// 2. if it is an operator,
|
|
// 2.1 if it is the first operator, push into `s` stack
|
|
// 2.2 if `s` stack already got element, compare the weight of opreators
|
|
// 2.3 pop `s` stack until the top most one got smaller precedence
|
|
// 3. if it is a bracket, push into stack `s`,
|
|
// 3. if it is a closing bracket, pop all element from `s` stack back to postfix,
|
|
// else return the result
|
|
|
|
// Function to convert infix expression to postfix expression
|
|
std::string infixToPostfix(const std::string &infix)
|
|
{
|
|
std::stack<char> s;
|
|
std::string postfix;
|
|
std::map<char, int> precedence = {{'+', 1}, {'-', 1}, {'*', 2}, {'/', 2}, {'(', 0}};
|
|
|
|
for (char c : infix)
|
|
{
|
|
if (std::isalnum(c))
|
|
{ // 1. if operand, add to postfix
|
|
postfix += c;
|
|
}
|
|
|
|
// 其實括號入面同括號出面嘅數你當佢兩條式計就得
|
|
else if (c == '(')
|
|
{ // 2. if '(', push to stack
|
|
s.push(c);
|
|
}
|
|
|
|
// 咁佢呢度關括號呀嘛,
|
|
// 咁佢咪會由個 stack 嗰度 port 返曬啲operator出嚟囉, 變咗可以 14+5*
|
|
else if (c == ')')
|
|
{ // 3. if ')', pop until '('
|
|
while (!s.empty() && s.top() != '(')
|
|
{
|
|
postfix += s.top();
|
|
s.pop();
|
|
}
|
|
if (!s.empty())
|
|
s.pop(); // pop '('
|
|
}
|
|
else
|
|
{ // 4. if operator, pop operators with greater or equal precedence
|
|
while (!s.empty() && precedence[c] <= precedence[s.top()])
|
|
{
|
|
postfix += s.top();
|
|
s.pop();
|
|
}
|
|
s.push(c); // push current operator
|
|
}
|
|
}
|
|
|
|
// 5. pop remaining operators, LIFO
|
|
while (!s.empty())
|
|
{
|
|
postfix += s.top();
|
|
s.pop();
|
|
}
|
|
|
|
return postfix;
|
|
}
|
|
|
|
// Function to evaluate postfix expression
|
|
|
|
// 2. pseudo code of the algorithm
|
|
// evaluate a postfix expression use stack,
|
|
// if it is an operand, push it into stack,
|
|
// if it is an operator, pop the top two elements, apply the operator, and push the result,
|
|
// if it is a bracket, pop until the matched bracket, then push it into stack,
|
|
// if the input is end, return the last element in stack,
|
|
// else error
|
|
|
|
int evaluatePostfix(const std::string &postfix)
|
|
{
|
|
std::stack<int> s;
|
|
|
|
for (char c : postfix)
|
|
{
|
|
if (std::isdigit(c))
|
|
{ // 1. if operand, push to stack
|
|
s.push(c - '0');
|
|
}
|
|
else
|
|
{ // 2. if operator, pop two operands, evaluate and push result
|
|
int op2 = s.top();
|
|
s.pop();
|
|
int op1 = s.top();
|
|
s.pop();
|
|
switch (c)
|
|
{
|
|
case '+':
|
|
s.push(op1 + op2);
|
|
break;
|
|
case '-':
|
|
s.push(op1 - op2);
|
|
break;
|
|
case '*':
|
|
s.push(op1 * op2);
|
|
break;
|
|
case '/':
|
|
s.push(op1 / op2);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return s.top(); // 3. result is the only element in stack
|
|
}
|
|
|
|
int main()
|
|
{
|
|
std::string infix;
|
|
// std::cout << "Enter an arithmetic expression: ";
|
|
// std::getline(std::cin, infix);
|
|
|
|
// --- part 2 iteration:
|
|
// 1,4,5,*,+
|
|
// 1,20,+
|
|
// 21
|
|
std::cout << "e.g. 1 1+4*5" << std::endl;
|
|
infix = "1+4*5";
|
|
std::string postfix = infixToPostfix(infix);
|
|
std::cout << "Postfix expression: " << postfix << std::endl;
|
|
|
|
int result = evaluatePostfix(postfix);
|
|
std::cout << "Result: " << result << std::endl;
|
|
|
|
// --- part 2 iteration:
|
|
// 1,4,+,5,*
|
|
// 5,5,*
|
|
// 25
|
|
std::cout << "e.g. 2 (1+4)*5" << std::endl;
|
|
infix = "(1+4)*5";
|
|
postfix = infixToPostfix(infix);
|
|
std::cout << "Postfix expression: " << postfix << std::endl;
|
|
result = evaluatePostfix(postfix);
|
|
std::cout << "Result: " << result << std::endl;
|
|
|
|
// --- part 2 iteration:
|
|
// 1,4,+,5,-
|
|
// 5,5,-
|
|
// 0
|
|
std::cout << "e.g. 3 1+4-5" << std::endl;
|
|
infix = "1+4-5";
|
|
postfix = infixToPostfix(infix);
|
|
std::cout << "Postfix expression: " << postfix << std::endl;
|
|
result = evaluatePostfix(postfix);
|
|
std::cout << "Result: " << result << std::endl;
|
|
|
|
// --- part 2 iteration:
|
|
// 1,4,5,*,+,5,*
|
|
// 1,20,+,5,*
|
|
// 21,5,*
|
|
// 105
|
|
std::cout << "e.g. 4 (1+4*5)*5" << std::endl;
|
|
infix = "(1+4*5)*5";
|
|
postfix = infixToPostfix(infix);
|
|
std::cout << "Postfix expression: " << postfix << std::endl;
|
|
|
|
result = evaluatePostfix(postfix);
|
|
std::cout << "Result: " << result << std::endl;
|
|
|
|
// --- part 2 iteration:
|
|
// 1,4,5,*,+,2,5,*,-
|
|
// =>1,20,+,2,5,*,-
|
|
// =>21,2,5,*,-
|
|
// =>21,10,-
|
|
// =>11
|
|
std::cout << "e.g. 5 (1+4*5)-2*5" << std::endl;
|
|
infix = "(1+4*5)-2*5";
|
|
postfix = infixToPostfix(infix);
|
|
std::cout << "Postfix expression: " << postfix << std::endl;
|
|
|
|
result = evaluatePostfix(postfix);
|
|
std::cout << "Result: " << result << std::endl;
|
|
|
|
return 0;
|
|
}
|