算数表达式计算 中缀表达式转后缀表达式

  1. 中缀表达式转后缀表达式

遍历中缀表达式中的数字和符号:

  1. 对于数字:直接输出
  2. 对于符号:
    1. 左括号:进栈  
    2. 运算符号:与栈顶符号进行优先级比较
  • 若栈顶符号优先级低:此符号进栈  

(默认栈顶若是左括号,左括号优先级最低)

  • 若栈顶符号优先级不低:将栈顶符号弹出并输出,之后进栈
  1. 右括号:将栈顶符号弹出并输出,直到匹配左括号,将左括号和右括号同时舍弃

遍历结束:将栈中的所有符号弹出并输出

  1. 基于后缀表达式运算

遍历后缀表达式中的数字和符号

    1. 对于数字:进栈
    2. 对于符号:
      1. 从栈中弹出右操作数
      2. 从栈中弹出左操作数
      3. 根据符号进行运算
      4. 将运算结果压入栈中

遍历结束:栈中的唯一数字为计算结果

package com.lg;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;

public class Computer {

	static HashMap<String, Integer> leveMap = new HashMap<>();
	static {
		leveMap.put("(", 0);
		leveMap.put("+", 1);
		leveMap.put("-", 1);
		leveMap.put("*", 2);
		leveMap.put("/", 2);
		leveMap.put("%", 2);
		leveMap.put("log", 3);
		leveMap.put("^", 4);
	}

	public static void main(String[] args) throws Exception {

		BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
		String readLine = bufferedReader.readLine();
		Queue<String> midleTolater = midleTolater(readLine);
		double computerBymidle = computerBymidle(midleTolater);
		System.out.println(computerBymidle);
	}

	/**
	 * 中缀表达式计算 遍历中缀表达式 数字直接入栈 遇到算数表达式 先弹出右操作数 再弹出左操作数 将计算结果压栈
	 * 
	 * 遍历结束:栈中的唯一数字为计算结果
	 * 
	 * @param queue
	 * @return
	 */
	public static double computerBymidle(Queue<String> queue) {
		Stack<Double> stack = new Stack<>();

		queue.forEach(r -> {
			if (isNumber(r)) {
				stack.push(Double.parseDouble(r));
			} else {
				Double right = stack.pop();
				Double left = stack.pop();
				if ("+".equals(r)) {
					stack.push(left + right);
				} else if ("-".equals(r)) {
					stack.push(left - right);
				} else if ("*".equals(r)) {
					stack.push(left * right);
				} else if ("/".equals(r)) {
					stack.push(left * right);
				} else if ("^".equals(r)) {
					stack.push(Math.pow(left, right));
				} else if ("%".equals(r)) {
					stack.push(left % right);
				}
			}
		});

		return stack.pop();
	}

	/**
	 * 中缀表达式转后缀表达式 遍历中缀表达式中的数字和符号: 
	 * 对于数字:直接输出 对于符号: 
	 * 左括号:进栈 运算符号:与栈顶符号进行优先级比较
	 * 若栈顶符号优先级低:
	 *         此符号进栈 (默认栈顶若是左括号,左括号优先级最低) 
	 *   若栈顶符号优先级不低:
	 *          将栈顶符号弹出并输出,之后进栈
	 * 右括号:将栈顶符号弹出并输出,直到匹配左括号,
	 * 将左括号和右括号同时舍弃
	 * 
	 *  遍历结束:将栈中的所有符号弹出并输出
	 * 
	 * @param str
	 * @return
	 */
	public static Queue<String> midleTolater(String str) {
		// 算数表达式数字与字符分割
		LinkedList<String> queue = new LinkedList<>();
		int start = 0;
		for (int i = 0; i < str.length(); i++) {
			if (!isNumber(str.charAt(i))) {
				if (start != i)
					queue.add(str.substring(start, i));
				queue.add(str.substring(i, i + 1));
				start = i + 1;
			}else if(isNumber(str.substring(i))) {
				queue.add(str.substring(i));
				break;
			}
		}
		queue.forEach(r -> System.out.println(r));
		// 中缀表达式转后缀表达式
		// 1、数字直接输出
		// 2、左括号直接入栈
		// 3、栈顶的优先级低直接入栈
		// 4、栈顶的优先级高 将栈顶符号弹出并输出,之后进栈
		// 5、右括号,栈顶元素弹出知道遇见右括号
		// 遍历结束:将栈中的所有符号弹出并输出

		Queue<String> laterString = new LinkedList<>();
		Stack<String> stack = new Stack<>();
		for (String element : queue) {
			if (isNumber(element)) {
				laterString.offer(element);
				continue;
			}
			if ("(".equals(element)) {
				stack.push(element);
				continue;
			}
			if (")".equals(element)) {
				while (!stack.isEmpty()) {
					String pop = stack.pop();
					if ("(".equals(pop)) {
						break;
					}
					laterString.offer(pop);
				}
				continue;
			}

			if (stack.isEmpty() || compareleve(element, stack.peek())) {
				stack.push(element);
			} else {
				laterString.add(stack.pop());
				stack.add(element);
			}
		}

		while (!stack.isEmpty()) {
			laterString.add(stack.pop());
		}
    laterString.forEach(r->System.out.print(","+r));
		return laterString;
	}

	public static boolean compareleve(String s1, String s2) {
		return leveMap.get(s1).compareTo(leveMap.getOrDefault(s2, 1)) >= 0;
	}

	public static boolean isNumber(char c) {

		return Character.isDigit(c) || '.' == c;
	}

	public static boolean isNumber(String ss) {

		try {
			Double.parseDouble(ss);
			return true;
		} catch (Exception e) {
			// TODO: handle exception
			return false;
		}
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值