signed

QiShunwang

“诚信为本、客户至上”

java实现逆波兰计算器

2021/1/28 14:39:26   来源:

文章目录

  • 前言
  • 一、功能要求
  • 二、思路分析
  • 三、中缀表达式转后缀表达式
  • 四、计算过程
  • 五、时间复杂度
  • 六、代码实现
    • 1.测试代码
    • 2.代码分析
  • 总结

前言

逆波兰计算器是用逆波兰表达式实现的一个计算器,逆波兰表达式又叫后缀表达式,我们使用该计算器时输入的是中缀表达式,然后计算器会把中缀表达式转成后缀表达式,这样更有利于计算器的运算,计算器使用的数据结构是栈。

一、功能要求

写一个控制台计算器,能够进行简单的加减乘除运算,支持小括号,要求使用逆波兰表达式实现。

二、思路分析

首先我们把输入的中缀表达式字符串存入list集合,操作集合中的元素比直接操作字符串更方便,然后我们再把中缀表达式的集合形式转成后缀表达式的集合形式,接下来就可以调用我们的计算函数进行计算。

三、中缀表达式转后缀表达式

在这里插入图片描述

中缀表达式转后缀表达式的核心思想也是借助了一个栈来进行操作,大家可以仔细看图中转的过程,并结合代码深入理解。

四、计算过程

在这里插入图片描述

计算过程并不复杂,相信大家学会了转后缀表达式后就能很轻易的实现该操作。

五、时间复杂度

逆波兰计算器的时间复杂度应该为O(n)

六、代码实现

1.测试代码

代码如下:

package com.yc.stack;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.Stack;

public class PolandNotation {
	
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		boolean flag = true;
		while(flag){
			System.out.println("请输入表达式:");//1+((2+3)*4)-5
			String expression = sc.next();
			//中缀表达式字符串转为list集合形式
			List<String> infixExprssion = toInfixExpressionList(expression);
			//中缀表达式转后缀表达式
			List<String> sufixExpression = parseSufixExpressionList(infixExprssion);
			//调用计算函数求解
			int res = calculate(sufixExpression);
			System.out.println(res);
		}
		sc.close();
	}
	/**
	 * 中缀表达式字符串转集合形式
	 * @param infixExprssion 中缀表达式字符串
	 * @return
	 */
	private static List<String> parseSufixExpressionList(List<String> infixExprssion) {
		Stack<String> stack = new Stack<String>();
		List<String> list = new ArrayList<String>();
		for(String item:infixExprssion){
			if(item.matches("\\d+")){
				list.add(item);
			}else if(item.equals("(")){
				stack.push(item);
			}else if(item.equals(")")){
				while(!stack.peek().equals("(")){
					list.add(stack.pop());
				}
				stack.pop();
			}else{
				while(!stack.isEmpty()&&Operation.priority(stack.peek())>=Operation.priority(item)){
					list.add(stack.pop());
				}
				stack.push(item);
			}
		}
		while(!stack.isEmpty()){
			list.add(stack.pop());
		}
		return list;
	}
	/**
	 * 中缀表达式转后缀表达式
	 * @param expression 中缀表达式集合形式
	 * @return
	 */
	private static List<String> toInfixExpressionList(String expression) {
		List<String> list = new ArrayList<String>();
		int index = 0;
		String str;
		do{
			if(expression.charAt(index)<48||expression.charAt(index)>57){
				list.add(expression.charAt(index)+"");
				index++;
			}else{
				str = "";
				while(index<expression.length()&&(expression.charAt(index)>=48&&expression.charAt(index)<=57)){
					str += expression.charAt(index);
					index++;
				}
				list.add(str);
			}
		}while(index<expression.length());
		return list;
	}
	/**
	 * 计算求解
	 * @param list 后缀表达式
	 * @return
	 */
	private static int calculate(List<String> list) {
		Stack<String> stack = new Stack<String>();
		for(String item:list){
			if(item.matches("\\d+")){
				stack.push(item);
			}else{
				int res = 0;
				int num2 = Integer.parseInt(stack.pop());
				int num1 = Integer.parseInt(stack.pop());
				if(item.equals("*")){
					res = num1*num2;
					stack.push(""+res);
				}else if(item.equals("/")){
					res = num1/num2;
					stack.push(""+res);
				}else if(item.equals("+")){
					res = num1+num2;
					stack.push(""+res);
				}else if(item.equals("-")){
					res = num1-num2;
					stack.push(""+res);
				}else{
					throw new RuntimeException("运算符有误");
				}
			}
		}
		return Integer.parseInt(stack.pop());
	}
}
class Operation{
	public static int ADD = 1;//加
	public static int SUB = 1;//减
	public static int MUL = 2;//乘
	public static int DIV = 2;//除
	/**
	 * 得到操作符的优先级,这里用的是自定义优先级
	 * @param operation 操作符
	 * @return
	 */
	public static int priority(String operation){
		int res = 0;
		switch (operation) {
		case "+":
			res = ADD;
			break;
		case "-":
			res = SUB;
			break;
		case "*":
			res = MUL;
			break;
		case "/":
			res = DIV;
			break;
		default:
			break;
		}
		return res;
	}
}

2.代码分析

代码主要分为两部分,中缀表达式转后缀表达式和计算函数

总结

这是一个栈的实际运用,前人太伟大,我们只能不断的学习和进步。