calc_res里面使用空格分割是个很不好的情况..需要保证转换的后缀式+-/*操作符是连在一起的 每个数字都需要用空格分离 ...
我懒的改了..这样导致代码逻辑有些乱 因为计算的后缀式res需要整理好才能计算正确
//数据结构与算法分析 栈c++实现
//缺点 需要一次性分配足够的栈空间 没有实现动态变长
//优点 大部分操作的消耗都是常量级别的
template <class type>
class stack
{
public:
stack(){}
~stack() { destroy(); }
void create_stack(size_t max_element)
{
if (!m_stack_base_ptr)
{
m_stack_base_ptr = new type[max_element];
m_max_element = max_element;
}
}
void push(type &t)
{
if(!is_full())
m_stack_base_ptr[++m_top_index] = t;
}
type& pop()
{
if(!is_empty())
--m_top_index;
return m_stack_base_ptr[m_top_index + 1];
}
type& top()
{
return is_empty() ? m_stack_base_ptr[0] : m_stack_base_ptr[m_top_index];
}
bool is_full()
{
return m_top_index >= m_max_element - 1;
}
bool is_empty()
{
return m_top_index == -1;
}
type& at(int idx)
{
return m_stack_base_ptr[idx];
}
void clear()
{
m_top_index = -1;
}
void destroy()
{
if (m_stack_base_ptr)
delete[]m_stack_base_ptr;
m_stack_base_ptr = nullptr;
}
size_t size()
{
return m_top_index + 1;
}
private:
type* m_stack_base_ptr = nullptr;
int m_top_index = -1;
int m_max_element = 0;
};
class input_argment
{
public:
input_argment(){}
input_argment(double number, bool is_operator = false, char op = '+')
{
m_number = number;
m_is_operator = is_operator;
m_operator = op;
}
double m_number;
bool m_is_operator = false;
char m_operator;
};
bool is_operator(char c, int &priority)
{
bool is_operator = true;
switch (c)
{
case '+':
case '-': break;
case '*': priority = 1; break;
case '/': priority = 1; break;
case '(': priority = 100; break;
case ')': priority = 100; break;
default:
is_operator = false;
break;
}
return is_operator;
}
bool is_operator(char c)
{
int p;
return is_operator(c, p);
}
//只看逻辑的话请把对res字符串操作的部分都删了...我看着都恶心
std::string reverse_polish(std::string &s)
{
stack<input_argment> my_stack;
my_stack.create_stack(100);
std::string res;
int idx = 0;
char op;
for (; idx < s.size(); ++idx)
{
bool is_operator_ = true;
int priority = 0;
op = s.at(idx);
//判断是不是操作符
is_operator_ = is_operator(op, priority);
res += s.at(idx);
//不是操作符就跳过当前循环
if (!is_operator_)
continue;
res.erase(--res.end());//删除输出的操作符
if (res.size()>0&& res[res.size()-1]!=' ')
res += ' ';
//栈为空 或者当前的操作符比栈顶操作符的优先级要高或者为(就直接压栈, )操作符的处理不需要压栈
if (my_stack.is_empty() || (!my_stack.is_empty() && my_stack.top().m_number < priority &&op != ')') ||op=='(')
{
my_stack.push(input_argment(priority, true, op));
}
else
{ //出栈
if (priority == 100) //遇到右括号了
{
//把(之前的操作符全部出栈
while (!my_stack.is_empty()&& my_stack.top().m_operator!='(')
res += my_stack.pop().m_operator;
my_stack.pop();//(出栈
}
else
{
//把所有优先级大于等于当前操作符的操作符全部出栈 直到遇到优先级更低的操作符或者(
while (!my_stack.is_empty() && my_stack.top().m_number >= priority &&my_stack.top().m_number != 100)
res += my_stack.pop().m_operator;
my_stack.push(input_argment(priority, true, op));//当前操作符压栈
}
//有时候会出现 1 2 3 * - 这个情况...因为我下面的计算是用空格来分割的,为了方便计算就每次加入一个操作符的时候就看看有没有这样
if (res.size() > 3 && res[res.size() - 2] == ' '&&is_operator(res[res.size() - 1]) &&is_operator(res[res.size() - 3]))
res.erase(----res.end());
res += ' ';
}
}
if (res[res.size() - 1] == ' ')
res.erase(--res.end());
else if(!is_operator(res[res.size()-1]))
res += ' ';
//将剩下的操作符出栈
while (!my_stack.is_empty())
res += my_stack.pop().m_operator;
//去掉多余的空格
auto p = res.find(" ");
while ( p!=std::string::npos )
{
res.erase(res.begin()+p);
p = res.find(" ");
}
return res;
}
void conver_notation_to_stack(std::string &s, stack<input_argment> &my_stack)
{
int priority = 0;
for (int i = s.size() - 1; i >= 0; --i)
{
if (is_operator(s[i], priority))
{
my_stack.push(input_argment(0, true, s[i]));
}
else
{
std::string res;
auto start = s.rfind(' ', i - 1);
if (start == std::string::npos)
res.assign(s.begin(), s.begin() + i+1);
else
res.assign(s.begin()+start, s.begin() + i+1);
my_stack.push(input_argment(atof(res.data())));
if (start == 0)
return;
else
i = s.rfind(' ',start-1) == std::string::npos ? start+1:start; //判断是不是只剩下一个数字了
}
}
}
double calc_res(stack<input_argment> &my_stack)
{
double v1, v2;
for (int i = my_stack.size() - 1; i >= 0; --i)
{
if (my_stack.at(i).m_is_operator)
{
v2 = my_stack.pop().m_number;
v1 = my_stack.pop().m_number;
switch (my_stack.at(i).m_operator)
{
case '+': my_stack.push(input_argment(v1 + v2)); break;
case '-': my_stack.push(input_argment(v1 - v2)); break;
case '*': my_stack.push(input_argment(v1 * v2)); break;
case '/': my_stack.push(input_argment(v1 / v2)); break;
}
}
else
{
my_stack.push(my_stack.at(i));
}
}
return my_stack.top().m_number;
}
int main()
{
std::string s,res;
s = "1+2+(1+2-3.5+(10*10-(10-20+((30-10)-(1+1.0)+1)-2)+(2-2)+3)-4)+100";
stack<input_argment> my_stack;
my_stack.create_stack(100);
//转化成计算式
res = reverse_polish(s);
//输出转化的计算公式
cout << res.data() << endl;
//将转化的计算式字符串转换为数据
conver_notation_to_stack(res, my_stack);
cout << calc_res(my_stack) << endl;
return 0;
}