基于后缀表达式的四则运算求值

2 篇文章 0 订阅
1 篇文章 0 订阅

最近学习数据结构,说到栈结构的一大应用就是基于后缀表达式的四则运算求值,那么什么是后缀表达式呢?让我们来简单举个栗子:
比如我们正常的数学表达式 3+1,我们称这种表达式为中缀表达式
其后缀表达式为3 1 +,嗯…,没错,就是把运算符号写在相互运算的两个数字的后面
我们再来一个复杂的栗子,中缀表达式:9*3+(10-4)*2-15/3 这样一个表达式,他的后缀表达式是什么样子的呢?让我们来一步一步分析一下吧
根据算法优先级可以分析出:
第一个*号相乘的两个数字为 9 和 3,其后缀表达式可以表示为9 3 *
第一个-号相减的数字为10 和 4,其后缀表达式可以表示为10 4 -
第二个*号相乘的两个数字为(10-4)的结果 和 2,故(10-4)*2的后缀表达式为10 4 - 2 *
第一个/号相除的两个数字为15和3,其后缀表达式可以表示为15 3 /
接下来是加号了,其两边操作数为9*3 和 (10-4)*2,故其后缀表达式为:
9 3 * 10 4 - 2 * +
最后,对于最后一个-号,其两端操作数分别为9*3+(10-4)*2 和 15/3 的结果,故最终表达式9*3+(10-4)*2-15/3的后缀表达式为:
9 3 * 10 4 - 2 * + 15 3 / -

以上为后缀表达式的原理分析过程,下面来讲解一下由中缀表达式获取后缀表达式的求解规则:
从左到右遍历中缀表达式的每个数字和符号,若是数字就输出,即成为后最表达式的一部分;若是符号,则判断其与栈顶符号的优先级,若是右括号,或优先级不高于栈顶符号,则栈顶元素依次出栈并输出,并将当前符号进栈,一直到最终输出后缀表达式为止。

现在我们得到了中缀表达式了,那么我们怎么求值呢?这里我们同样需要一个栈结构辅助,用于管理数值的进出,其执行规则如下:
从左到右遍历后缀表达式的每个数字和符号,若是数字就进栈,若是符号,就将处于栈顶的两个元素出栈,进行运算,然后将结果进栈,一直到最终获得结果

前面说明了原理,接下来直接上代码了,我基于此实现了一个四则运算类,其定义如下:

#pragma once
#include <string>
#include"RL_Stack.h"
#include <map>
#include <queue>
namespace RL
{
	class QuadricOperation
	{
	public:
		// 定义运算符优先级
		const std::map<std::string, int> m_operator_priority =
		{
			{"+",1},{ "-",1 },{ "*",2 },{ "/",2 }
		};

	public:
		QuadricOperation();
		~QuadricOperation();
		void SetExpression(const std::string &); // 设置中缀表达式
		double GetValue(); // 获取最后结果
		//std::queue<std::string> GetPrefixExpression(); // 
		std::queue<std::string> GetInfixExpression();// 获取后缀表达式
	private:
		// 中缀表达式转后缀表达式
		void calculation_infix_expression(); 
		void calculation_symbol_stack(std::string _str);

		// 使用后缀表达式进行求值
		void calculation_result();
	private:
		//std::string m_prefix_expression; // 前缀表达式
		//std::string m_infix_expression;  // 中缀表达式
		std::queue<std::string> m_prefix_expression; // 中缀表达式
		std::queue<std::string> m_infix_expression; // 后缀表达式

		LinkStack<std::string> m_symbol_stack; // 符号栈
		LinkStack<double> m_value_stack; // 数值栈
		double m_result; // 计算结果
		bool m_is_calculated; // 是否已经计算过了
	};
}

其实现代码如下:

#include "stdafx.h"
#include "QuadricOperation.h"
//#include 

namespace RL
{
	QuadricOperation::QuadricOperation()
	{
	}


	QuadricOperation::~QuadricOperation()
	{

	}

	void QuadricOperation::SetExpression(const std::string &expression)
	{
		m_is_calculated = false;
		std::string vel = "";
		for (int i = 0; i < expression.length(); i++)
		{
			if ((expression[i] >= '0' && expression[i] <= '9') || expression[i] == '.')
			{
				vel += expression[i];
			}
			else
			{
				if (vel.length()>0)
				{
					m_prefix_expression.push(vel);
					vel = "";
				}
				std::string _vel = "";
				_vel+=expression[i];
				m_prefix_expression.push(_vel);
			}
		}
		if (vel.length()>0)
		{
			m_prefix_expression.push(vel);
		}
	}
	double QuadricOperation::GetValue()
	{
		if (!m_is_calculated)
		{
			if (m_infix_expression.empty())
			{
				calculation_infix_expression();
			}
			calculation_result();
			m_is_calculated = true;
		}
		return m_result;
	}
	std::queue<std::string> QuadricOperation::GetPrefixExpression()
	{
		return m_prefix_expression;
	}
	std::queue<std::string> QuadricOperation::GetInfixExpression()
	{
		if (m_infix_expression.empty())
		{
			calculation_infix_expression();
		}
		return m_infix_expression;
	}
	void QuadricOperation::calculation_symbol_stack(std::string _str)
	{
		if (_str == "(")
		{
			m_symbol_stack.Push(_str);
			return;
		}
		if (m_operator_priority.find(_str) != m_operator_priority.end())
		{
			if (m_symbol_stack.isEmpty())
			{
				m_symbol_stack.Push(_str);
				return;
			}

			std::string _symbol;
			m_symbol_stack.GetPop(_symbol);
			if (_symbol == "(")
			{
				m_symbol_stack.Push(_str);
				return;
			}

			while (!m_symbol_stack.isEmpty())
			{
				std::string _symbol;
				m_symbol_stack.GetPop(_symbol);
				if (_symbol == "(")
				{
					m_symbol_stack.Pop();
					m_symbol_stack.Push(_str);
					return;
				}
				if (m_operator_priority.at(_symbol) < m_operator_priority.at(_str))
				{
					m_symbol_stack.Push(_str);
					return;
				}
				m_symbol_stack.Pop();
				m_infix_expression.push(_symbol);
			}
			m_symbol_stack.Push(_str);
			return;
		}
		if (_str == ")")
		{
			while (!m_symbol_stack.isEmpty())
			{
				std::string _symbol;
				m_symbol_stack.GetPop(_symbol);
				if (_symbol == "(")
				{
					m_symbol_stack.Pop();
					//m_symbol_stack.Push(_str);
					return;
				}
				m_symbol_stack.Pop();
				m_infix_expression.push(_symbol);
			}
		}
	}

	void QuadricOperation::calculation_infix_expression()
	{
		while (!m_prefix_expression.empty())
		{
			std::string _str = m_prefix_expression.front();
			m_prefix_expression.pop();
			if (m_operator_priority.find(_str) == m_operator_priority.end() && _str != "("&& _str != ")")
			{
				m_infix_expression.push(_str);
				continue;
			}
			calculation_symbol_stack(_str);
		}
		while (!m_symbol_stack.isEmpty())
		{
			std::string _symbol = m_symbol_stack.Pop();
			m_infix_expression.push(_symbol);
		}
	}
	void QuadricOperation::calculation_result()
	{
		while (!m_infix_expression.empty())
		{
			std::string _str = m_infix_expression.front();
			m_infix_expression.pop();
			if (m_operator_priority.find(_str) != m_operator_priority.end())
			{
				double _vel1 = m_value_stack.Pop();
				double _vel2 = m_value_stack.Pop();
				if (_str == "+")
				{
					m_value_stack.Push(_vel2 + _vel1);
				}
				if (_str == "-")
				{
					m_value_stack.Push(_vel2 - _vel1);
				}
				if (_str == "*")
				{
					m_value_stack.Push(_vel2 * _vel1);
				}
				if (_str == "/")
				{
					m_value_stack.Push(_vel2 / _vel1);
				}
				continue;
			}
			double _vel = atof(_str.c_str());
			m_value_stack.Push(_vel);
		}
		m_result = m_value_stack.Pop();
	}
}

另外说明一下,这里使用的栈是本人自己实现的栈结构,如果需要可以去这里获取:https://blog.csdn.net/m0_45074715/article/details/127721573
当然,你也可以给将相应代码改成你自己的或者标准库的栈

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值