C++ 中缀表达式转后缀表达式
关于后缀表达式如何计算,这里不做过多叙述。以下提供两种方式供参考,第二个种方式粗略的写了计算方式。
方式一 —— 栈
该方式主要是通过栈的数据结构,规定运算符的优先级进行处理即可。 参考链接:https://blog.csdn.net/liudongdong19/article/details/80767156
源码(C++)
#include <iostream>
#include <map>
#include <string>
#include <stack>
using namespace std;
map<char, int> priority;
bool JudgeNumber(char s) { return s - '0' >= 0 && s - '0' <= 9 ? true : false; }
int GetPriority(char c)
{
auto iter = priority.find(c);
return iter == priority.end() ? -1 : iter->second;
}
string GetSuffix(string prefixStr)
{
string suffixStr;
stack<char> s;
s.push('#');
while (!prefixStr.empty())
{
if (JudgeNumber(prefixStr[0]) || prefixStr[0] == '.')
{
suffixStr.push_back(prefixStr[0]);
prefixStr.erase(prefixStr.begin());
}
else
{
if (!suffixStr.empty())
{
if (JudgeNumber(suffixStr.back()))
suffixStr.push_back(' ');
}
if (prefixStr[0] == ')')
{
while (s.top() != '(')
{
suffixStr.push_back(s.top());
s.pop();
suffixStr.push_back(' ');
}
prefixStr.erase(prefixStr.begin());
s.pop();
}
else if (prefixStr[0] == '(')
{
s.push(prefixStr[0]);
prefixStr.erase(prefixStr.begin());
}
else if (GetPriority(prefixStr[0]) > GetPriority(s.top()))
{
s.push(prefixStr[0]);
prefixStr.erase(prefixStr.begin());
}
else if (GetPriority(prefixStr[0]) <= GetPriority(s.top()))
{
while (s.top() != '(' && s.top() != '#')
{
suffixStr.push_back(s.top());
suffixStr.push_back(' ');
s.pop();
}
s.push(prefixStr[0]);
prefixStr.erase(prefixStr.begin());
}
}
}
while (s.top() != '#')
{
suffixStr.push_back(' ');
suffixStr.push_back(s.top());
s.pop();
}
return suffixStr;
}
int main()
{
priority = { {'#',0},{'(',1}, {'+',3},{'-',3} ,{'*',5},{'/',5},{')',6} };
string s = "(2+3)*2";
cout << GetSuffix(s) << endl;
return 0;
}
方式二 —— 二叉树
思路如下(以下思路仅供参考):
??比如对于中缀表达式:2*(3*5+2)+7/1-4,我们使用一个vector<string>的动态数组存储数字(整型和非整数);使用stack<char>存储运算符号,由于优先级的关系,我们使用’#'来表示最低优先级(其它符号均可)。
??现假定动态数组vector<string> arr和stack<char> s,一开始第一轮我们将2插入至arr,‘*‘的优先级比’#‘高,直接插入s中,但是由于当前没有两个以上数字,所以我们继续处理中缀表达式,s中插入’(‘运算符,之后一直处理数字和符号(s中如果有’(‘运算符则直接无条件插入),直至遇到’)‘符号,此时,当前arr = {2,3,5,2},s = {’#’,‘*’,‘(’,‘*’,‘+’};我们对括号中的符号以及相应数字进行处理,结果如下:
??此时中缀表达式只剩下:+7/1-4。继续处理,如下:
??最后,将剩余的符号和数字进行处理。
源码(C++)
#include <iostream>
#include <string>
#include <vector>
#include <stack>
#include <map>
#include <algorithm>
using namespace std;
static map<char, int> priority;
struct TreeNode
{
TreeNode* left;
TreeNode* right;
string val;
TreeNode(string val_) :left(nullptr), right(nullptr), val(val_) {};
};
static bool JudgeNumber(char s) { return s - '0' >= 0 && s - '0' <= 9 ? true : false; }
static int GetPriority(char c)
{
auto iter = priority.find(c);
return iter == priority.end() ? -1 : iter->second;
}
static bool IsLeftSymbol(stack<char> stacks)
{
while (!stacks.empty())
{
if (stacks.top() == '(')
return true;
stacks.pop();
}
return false;
}
void SetRightTree(TreeNode* curNode, char c, string rightNum)
{
stack<TreeNode*> stacks;
while (curNode->right != nullptr)
{
stacks.push(curNode);
curNode = curNode->right;
}
TreeNode* node = new TreeNode(string(1, c));
node->left = stacks.top()->right;
node->right = new TreeNode(rightNum);
stacks.top()->right = node;
}
void SetTopTree(stack<char>& s, vector<string>& arr, TreeNode*& curNode)
{
if (arr.size() == 0)return;
TreeNode* node = new TreeNode(string(1, s.top()));
s.pop();
node->left = curNode;
node->right = new TreeNode(arr[arr.size() - 1]);
arr.pop_back();
curNode = node;
}
void SetRootNode(stack<char>& s, vector<string>& arr, TreeNode*& curNode)
{
curNode = new TreeNode(string(1, s.top()));
s.pop();
curNode->left = new TreeNode(arr[arr.size() - 1]);
arr.pop_back();
curNode->right = new TreeNode(arr[arr.size() - 1]);
arr.pop_back();
}
void SetTree(stack<char>& s, vector<string>& arr, TreeNode*& curNode, bool flag)
{
if (curNode == nullptr)
SetRootNode(s, arr, curNode);
else if (GetPriority((curNode->val[0])) < GetPriority(s.top()) && !flag)
{
SetRightTree(curNode, s.top(), arr[arr.size() - 1]);
s.pop();
arr.pop_back();
}
else if (GetPriority((curNode->val[0])) >= GetPriority(s.top()) || flag)
SetTopTree(s, arr, curNode);
}
TreeNode* GetPrefixTree(string str)
{
TreeNode* beginNode = nullptr;
vector<string> arr;
stack<char> s;
s.push('#');
bool flag = false;
while (!str.empty())
{
if (!IsLeftSymbol(s) && beginNode == nullptr && arr.size() == 2)
SetRootNode(s, arr, beginNode);
if (JudgeNumber(str[0]))
{
int count = 0;
while (count < str.size())
{
if (str[count] == '.' || JudgeNumber(str[count]))count++;
else break;
}
arr.push_back(string(str.begin(), str.begin() + count).c_str());
str.erase(str.begin(), str.begin() + count);
}
else
{
if (str[0] == ')')
{
str.erase(str.begin());
while (s.top() != '#')
{
if (s.top() == '(')
{
s.pop();
flag = true;
continue;
}
SetTree(s, arr, beginNode, flag);
}
if (GetPriority(str[0]) >= GetPriority(beginNode->val[0]))
flag = true;
else
flag = false;
}
else if (str[0] == '(')
{
s.push(str[0]);
str.erase(str.begin());
}
else if (IsLeftSymbol(s))
{
s.push(str[0]);
str.erase(str.begin());
}
else if (GetPriority(str[0]) >= GetPriority(s.top()))
{
if (beginNode != nullptr && s.top() != '#')
SetTopTree(s, arr, beginNode);
s.push(str[0]);
str.erase(str.begin());
}
else if (GetPriority(str[0]) < GetPriority(s.top()))
{
SetTree(s, arr, beginNode, flag);
s.push(str[0]);
str.erase(str.begin());
}
}
}
if (beginNode != nullptr)
SetTree(s, arr, beginNode, flag);
return beginNode;
}
double GetValue(TreeNode* node)
{
if (!JudgeNumber(node->val[0]))
{
if (node->val == "+")
return GetValue(node->left) + GetValue(node->right);
else if (node->val == "-")
return GetValue(node->left) - GetValue(node->right);
else if (node->val == "*")
return GetValue(node->left) * GetValue(node->right);
else
return GetValue(node->left) / GetValue(node->right);
}
else
return atof(node->val.c_str());
}
int main()
{
priority = { {'#',0},{'(',1}, {'+',3},{'-',3} ,{'*',5},{'/',5},{')',6} };
string s = "2*(3*5+2)+7/1-4";
TreeNode* node = GetPrefixTree(s);
double res = GetValue(node);
cout << GetValue(node) << endl;
return 0;
}
|