1.概念

什么是中缀表达式,什么是后缀表达式?

从小学开始学习的四则运算,例如:3 (5*(2 3) 7) 类似这种表达式就是中缀表达式。中缀表达式人脑很容易理解,各个算符的优先级,人脑也很容易判断,先算括弧里的,再算*,再算 ,-

但是这种表达式很不利于计算机计算,通过某种方式把前缀表达式转换为后缀表达式方便计算机进行计算,如3 (5*(2 3) 7)的后缀表达式就是3,5,2,3, ,*,7, , 。这个表达式计算机很容易计算,为什么容易计算,通过算法流程2,就会一个深入的理解。

2.算法流程

如何把中缀表达式转换成后缀表达式?比如说3 (5*(2 3) 7)的转成后缀表达式的流程如何?

操作符优先级:

  • ,- 小于*,/
  • 等于 -
  • * 等于 /

左括号和右括号作为特殊操作符特殊处理。(碰到’(’不用判断优先级直接入操作符栈,碰到’)’,也不用判断优先级,直接出操作符栈)

大致算法掌握以下几个流程:

准备两个栈,一个是数字栈A,一个是操作符栈( ,-,*,/(,))B等

1.0 对于数字栈A,遇到数字直接入栈A。

2.0 对于操作符栈B,分几种情况

2.1 碰到 ‘(‘操作符直接入栈

2.2 碰到 ‘)’操作符,不停的把操作符栈B出栈,直到遇到’)’。(把’(’到’)’之间的弹出的操作符依次入栈A)

2.3 碰到’ ,-,* /’比较当前元素(假设当前元素current)和B栈栈顶的操作符(假设栈顶元素是top)的优先级.

2.3.1 如果top >= current, B栈出栈且循环比较,直到top < current退出循环,且把 current入栈

2.3.2 如果top < current, 直接把current入B栈

3.0 扫描完整个字符串,如果B栈中还有操作符,依次出栈入A

按照上面算法演示3 (5*(2 3) 7)的流程:

1,碰到3,3入A栈 [3,]
2,碰到 ,入B栈   [ ,]
3,碰到(,入B栈   [ ,(]
4,碰到5,入A栈   [3,5]
5,碰到*,*的优先级大于 (,入B栈[ ,(,*]
6,碰到(,入B栈[ ,(,*,(]
7,碰到2,入A栈   [3,5,2]
8,碰到 ,入B栈[ ,(,*,(, ]
9,碰到3,入A栈   [3,5,2,3]
10,碰到),弹出B栈,直接到 ‘(‘,把弹出的操作符入A栈。B:[ ,(,*] A:[3,5,2,3, ]
11,碰到 , 的优先级小于B的栈顶元素 *,所以*从B出栈,入A,并把 入B。B:[ ,(, ] A:[3,5,2,3, ,*]
12,碰到7,入A栈   [3,5,2,3, ,*,7]
13,碰到),弹出B栈,直接到 ‘(‘,把弹出的操作符入A栈。B:[ ] A:[3,5,2,3, ,*,7, ]
14, 扫描完整个字符串,判断B是否为空,不为空把B栈的元素弹出,入A。当前不为空,所以最终A栈的元素为 A:[3,5,2,3, ,*,7, , ]

所以最终A的后缀表达式是3,5,2,3, ,*,7, ,

计算机拿到这个会怎么计算呢?流程如下:

  • 碰到数字直接入栈
  • 碰到操作符,直接弹出两个栈顶元素,通过操作符计算,把结果压入栈

通过步骤1,2循环计算,最终栈里只会有一个元素,这个就是表达式的结果。

我们来演练一下:

1,碰到数字3,5,2,3直接入栈A[3,5,2,3]
2,碰到 ,弹出栈顶2,3,相加得5 入栈A[3,5,5]
3,碰到*,弹出栈顶5,5,相乘得25 入栈A[3,25]
4,碰到7,直接入栈A[3,25,7]
5,碰到 ,弹出栈顶25,7,相加得32 入栈A[3,32]
6,碰到 ,弹出栈顶3,32,相加得35 入栈A[35]

通过上面可以得知,计算机很容易计算,从左扫描到右就能把结果得出。

3 代码实现

mid2post 求后缀表达式

calcPostExp 拿到后缀表达式求值

cmpPriority 优先级比较

//优先级
bool cmpPriority(char top, char cur)//比较当前字符与栈顶字符的优先级,若栈顶高,返回true
{
	if ((top == ' ' || top == '-') && (cur == ' ' || cur == '-'))
		return true;
	if ((top == '*' || top == '/') && (cur == ' ' || cur == '-' || top == '*' || top == '/'))
		return true;
	if (cur == ')')
		return true;
	return false;
}

求后缀表达式求值

vector<string> mid2post(string &str)
{

	vector<string>vstr;
	stack<char>cstack;
	for (int i = 0;i<str.size();  i)//扫描字符串
	{
		string temp = "";
		if (str[i] >= '0' && str[i] <= '9')//若是数字
		{
			temp  = str[i];
			while (i   1<str.size() && str[i   1] >= '0' && str[i   1] <= '9')
			{
				temp  = str[i   1];//若是连续数字
				  i;
			}
			vstr.push_back(temp);
		}
		else if (cstack.empty() || str[i] == '(')//若栈空或者字符为'('
			cstack.push(str[i]);
		else if (cmpPriority(cstack.top(), str[i]))//若栈顶元素优先级较高,栈顶元素出栈
		{
			if (str[i] == ')')//若当前字符是右括号,栈中元素出栈,入字符串数组中,直到遇到'('
			{
				while (!cstack.empty() && cstack.top() != '(')
				{
					temp  = cstack.top();
					cstack.pop();
					vstr.push_back(temp);
					temp = "";
				}
				cstack.pop();
			}
			else//栈中优先级高的元素出栈,入字符串数组,直到优先级低于当前字符
			{
				while (!cstack.empty() && cmpPriority(cstack.top(), str[i]))
				{
					temp  = cstack.top();
					cstack.pop();
					vstr.push_back(temp);
					temp = "";
				}
				cstack.push(str[i]);
			}
		}
		else//当前字符优先级高于栈顶元素,直接入栈
			cstack.push(str[i]);
	}
	while (!cstack.empty())//栈中还存在运算符时,出栈,存入字符串数组
	{
		string temp = "";
		temp  = cstack.top();
		cstack.pop();
		vstr.push_back(temp);
	}
	return vstr;
}

对后缀表达式进行求值,主要是根据运算符取出两

int calcPostExp(vector<string> & vstr)//对后缀表达式进行求值,主要是根据运算符取出两个操作数进行运算
{
	int num, op1, op2;
	stack<int>opstack;
	for (int i = 0;i<vstr.size();  i)
	{
		string temp = vstr[i];
		if (temp[0] >= '0' && temp[0] <= '9')//如果当前字符串是数字,利用字符串流转化为int型
		{
			stringstream ss;
			ss << temp;
			ss >> num;
			opstack.push(num);
		}
		else if (vstr[i] == " ")//若是操作符,取出两个操作数,进行运算,并将结果存入
		{
			op2 = opstack.top();
			opstack.pop();
			op1 = opstack.top();
			opstack.pop();
			opstack.push(op1   op2);
		}
		else if (vstr[i] == "-")
		{
			op2 = opstack.top();
			opstack.pop();
			op1 = opstack.top();
			opstack.pop();
			opstack.push(op1 - op2);
		}
		else if (vstr[i] == "*")
		{
			op2 = opstack.top();
			opstack.pop();
			op1 = opstack.top();
			opstack.pop();
			opstack.push(op1*op2);
		}
		else if (vstr[i] == "/")
		{
			op2 = opstack.top();
			opstack.pop();
			op1 = opstack.top();
			opstack.pop();
			opstack.push(op1 / op2);
		}
	}
	return opstack.top();//最终的栈顶元素就是求解的结果
}

到此这篇关于详解Java中缀表达式的实现的文章就介绍到这了,更多相关Java中缀表达式内容请搜索Devmax以前的文章或继续浏览下面的相关文章希望大家以后多多支持Devmax!

详解Java中缀表达式的实现的更多相关文章

  1. Java利用POI实现导入导出Excel表格

    这篇文章主要为大家详细介绍了Java利用POI实现导入导出Excel表格,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  2. Java 阻塞队列BlockingQueue详解

    本文详细介绍了BlockingQueue家庭中的所有成员,包括他们各自的功能以及常见使用场景,通过实例代码介绍了Java 阻塞队列BlockingQueue的相关知识,需要的朋友可以参考下

  3. Java Bean 作用域及它的几种类型介绍

    这篇文章主要介绍了Java Bean作用域及它的几种类型介绍,Spring框架作为一个管理Bean的IoC容器,那么Bean自然是Spring中的重要资源了,那Bean的作用域又是什么,接下来我们一起进入文章详细学习吧

  4. Java实现世界上最快的排序算法Timsort的示例代码

    Timsort 是一个混合、稳定的排序算法,简单来说就是归并排序和二分插入排序算法的混合体,号称世界上最好的排序算法。本文将详解Timsort算法是定义与实现,需要的可以参考一下

  5. Java日期工具类的封装详解

    在日常的开发中,我们难免会对日期格式化,对日期进行计算,对日期进行校验,为了避免重复写这些琐碎的逻辑,我这里封装了一个日期工具类,方便以后使用,直接复制代码到项目中即可使用,需要的可以参考一下

  6. Java设计模式之模板方法模式Template Method Pattern详解

    在我们实际开发中,如果一个方法极其复杂时,如果我们将所有的逻辑写在一个方法中,那维护起来就很困难,要替换某些步骤时都要重新写,这样代码的扩展性就很差,当遇到这种情况就要考虑今天的主角——模板方法模式

  7. Java 中 Class Path 和 Package的使用详解

    这篇文章主要介绍了Java 中 Class Path和Package的使用详解,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的朋友可以参考一下

  8. java SpringBoot 分布式事务的解决方案(JTA+Atomic+多数据源)

    这篇文章主要介绍了java SpringBoot 分布式事务的解决方案(JTA+Atomic+多数据源),文章围绕主题展开详细的内容介绍,具有一定的参考价值,感兴趣的小伙伴可以参考一下

  9. Java一维数组和二维数组元素默认初始化值的判断方式

    这篇文章主要介绍了Java一维数组和二维数组元素默认初始化值的判断方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  10. java实现emqx设备上下线监听详解

    这篇文章主要为大家介绍了java实现emqx设备上下线监听详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

随机推荐

  1. 基于EJB技术的商务预订系统的开发

    用EJB结构开发的应用程序是可伸缩的、事务型的、多用户安全的。总的来说,EJB是一个组件事务监控的标准服务器端的组件模型。基于EJB技术的系统结构模型EJB结构是一个服务端组件结构,是一个层次性结构,其结构模型如图1所示。图2:商务预订系统的构架EntityBean是为了现实世界的对象建造的模型,这些对象通常是数据库的一些持久记录。

  2. Java利用POI实现导入导出Excel表格

    这篇文章主要为大家详细介绍了Java利用POI实现导入导出Excel表格,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  3. Mybatis分页插件PageHelper手写实现示例

    这篇文章主要为大家介绍了Mybatis分页插件PageHelper手写实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  4. (jsp/html)网页上嵌入播放器(常用播放器代码整理)

    网页上嵌入播放器,只要在HTML上添加以上代码就OK了,下面整理了一些常用的播放器代码,总有一款适合你,感兴趣的朋友可以参考下哈,希望对你有所帮助

  5. Java 阻塞队列BlockingQueue详解

    本文详细介绍了BlockingQueue家庭中的所有成员,包括他们各自的功能以及常见使用场景,通过实例代码介绍了Java 阻塞队列BlockingQueue的相关知识,需要的朋友可以参考下

  6. Java异常Exception详细讲解

    异常就是不正常,比如当我们身体出现了异常我们会根据身体情况选择喝开水、吃药、看病、等 异常处理方法。 java异常处理机制是我们java语言使用异常处理机制为程序提供了错误处理的能力,程序出现的错误,程序可以安全的退出,以保证程序正常的运行等

  7. Java Bean 作用域及它的几种类型介绍

    这篇文章主要介绍了Java Bean作用域及它的几种类型介绍,Spring框架作为一个管理Bean的IoC容器,那么Bean自然是Spring中的重要资源了,那Bean的作用域又是什么,接下来我们一起进入文章详细学习吧

  8. 面试突击之跨域问题的解决方案详解

    跨域问题本质是浏览器的一种保护机制,它的初衷是为了保证用户的安全,防止恶意网站窃取数据。那怎么解决这个问题呢?接下来我们一起来看

  9. Mybatis-Plus接口BaseMapper与Services使用详解

    这篇文章主要为大家介绍了Mybatis-Plus接口BaseMapper与Services使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  10. mybatis-plus雪花算法增强idworker的实现

    今天聊聊在mybatis-plus中引入分布式ID生成框架idworker,进一步增强实现生成分布式唯一ID,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

返回
顶部