数据结构与算法--第5篇(前、中、后缀表达式&逆波兰计算器)

一,前、中、后缀表达式

1,前缀表达式(波兰表达式):

前缀表达式: 又称波兰表达式,运算符位于表达式之前;
前缀表达式计算机求值: 从右至左扫描前缀表达式,将数字压栈,遇到运算符时,弹出两个数值,用运算符进行运算,然后在将运算结果压栈,反复直到表达式最左端,最后得到结果;如:(- * + 3 4 5 6)==》(3+4)*5-6 ,6543全部压栈,遇到+,弹出3,4得3+4=7压栈,再遇到 * 弹出7,5…

2,中缀表达式

中缀表达式: 即我们常用的数学表达式,如(3+4)*5-6,但是计算机不方便操作(数据结构与算法–第四篇(栈&模拟计算器)),所以一般都转为前、后缀表达式,多为后缀表达式;

3,后缀表达式(逆波兰表达式)

后缀表达式: 又称逆波兰表达式,与前缀表达式相似,操作符位于需要操作的数字之后,如(3+4)*5-6==》3 4 + 5 * 6 -
表达式转换
后缀表达式计算机求值: 从左至右扫描后缀表达式,遇到数字就压栈,遇到运算符就弹出栈顶前两个用该运算符运算,结果再入栈,重复上述直至达到表达式最右端,最后得到结果;

4,中缀转后缀表达式

转换思路:

  1. 初始化两个栈,运算符栈s1和存储中间结果栈s2;
  2. 从左至右扫描中缀表达式;
  3. 遇到数值时压入s2;
  4. 遇到运算符时,比较其与s1栈顶运算符的优先级;
    4.1.如果s1为空,或栈顶运算符为左括号‘(’,则直接将次运算符入栈;
    4.2.否则,若优先级比栈顶运算符高,也直接压入s1;
    4.3.否则,将s1栈顶的运算符弹出压入s2,再次转到(4.1)与s1中新的栈顶运算符比较;
  5. 遇到括号时:
    5.1.如果是‘(’,直接压入s1;
    5.2.如果是‘)’,则依次弹出s1栈顶的运算符,压入s2,直到遇到‘(’为止,此时直接丢弃括号;
  6. 重复步骤2-5,直到表达式最右边;
  7. 将s1中的表达式依次弹出压入s2;
  8. 依次弹出s2的元素,结果逆序即为中缀表达式转后缀的结果;

代码实现:

	public static String suffixString(List<String> suffixStringList) {
        StringBuffer sb = new StringBuffer();
        for (String s : suffixStringList) {
            sb.append(s + " ");
        }
        return sb.toString().substring(0, sb.length() - 1);
	}
	public static List<String> toSuffixStringList(List<String> infixStringList) {
        Stack<String> stack = new Stack<>();
        int size = infixStringList.size();
        List<String> suffixStringList = new ArrayList<>(size);
        for (String s : infixStringList) {
            if (s.matches("\\d+")) {
                suffixStringList.add(s);
            } else if ("(".equals(s)) {
                stack.push(s);
            } else if (")".equals(s)) {
                while (!"(".equals(stack.peek())) {
                    suffixStringList.add(stack.pop());
                }
                stack.pop();//将符号栈的"("弹出
            } else {
                while (stack.size() != 0 && (symblo(s) <= symblo(stack.peek()))) {
                    suffixStringList.add(stack.pop());
                }
                stack.push(s);
            }
        }
        while (stack.size() != 0) {
            suffixStringList.add(stack.pop());
        }
        return suffixStringList;

    }

    public static int symblo(String symbol) {
        int result = 0;
        switch (symbol) {
            case "+":
            case "-":
                result = 1;
                break;
            case "*":
            case "/":
                result = 2;
                break;
            default:
                break;
        }
        return result;
    }

5,逆波兰计算器

package com.stack;

import sun.awt.geom.AreaOp;

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

/**
 * @param
 * @Author: AaNeei
 * @Date: 2019/6/14  22:37
 * @Description: 游学网
 * @throws:
 */
public class ReversePolishCalculator {

    public static void main(String[] args) {
        String infixNotation = "111+((2+3)*4)-5";
        List<String> stringList = infixToStringList(infixNotation);
        List<String> suffixStringList = toSuffixStringList(stringList);
        String s = suffixString(suffixStringList);
        System.out.println(stringList + "===>" + suffixStringList + "===>" + s);
        List<String> string = getListString(s);
        int calculate = calculate(string);
        System.out.println(infixNotation + "=" + calculate);
    }

    public static String suffixString(List<String> suffixStringList) {
        StringBuffer sb = new StringBuffer();
        for (String s : suffixStringList) {
            sb.append(s + " ");
        }
        return sb.toString().substring(0, sb.length() - 1);
    }

    public static List<String> toSuffixStringList(List<String> infixStringList) {
        Stack<String> stack = new Stack<>();
        int size = infixStringList.size();
        List<String> suffixStringList = new ArrayList<>(size);
        for (String s : infixStringList) {
            if (s.matches("\\d+")) {
                suffixStringList.add(s);
            } else if ("(".equals(s)) {
                stack.push(s);
            } else if (")".equals(s)) {
                while (!"(".equals(stack.peek())) {
                    suffixStringList.add(stack.pop());
                }
                stack.pop();//将符号栈的"("弹出
            } else {
                while (stack.size() != 0 && (symblo(s) <= symblo(stack.peek()))) {
                    suffixStringList.add(stack.pop());
                }
                stack.push(s);
            }
        }
        while (stack.size() != 0) {
            suffixStringList.add(stack.pop());
        }
        return suffixStringList;

    }

    public static int symblo(String symbol) {
        int result = 0;
        switch (symbol) {
            case "+":
            case "-":
                result = 1;
                break;
            case "*":
            case "/":
                result = 2;
                break;
            default:
                break;
        }
        return result;
    }

    public static List<String> infixToStringList(String infixNotation) {
        int length = infixNotation.length();
        List<String> stringList = new ArrayList<>(length);
        int i = 0;
        char ch;
        do {
            if ((ch = infixNotation.charAt(i)) < 48 || (ch = infixNotation.charAt(i)) > 57) {
                stringList.add(ch + "");
                i++;
            } else {
                StringBuffer sb = new StringBuffer("");
                while (i < length && (ch = infixNotation.charAt(i)) >= 48 && (ch = infixNotation.charAt(i)) <= 57) {
                    sb.append(ch + "");
                    i++;
                }
                stringList.add(sb.toString());
            }
        } while (i < length);
        return stringList;

    }

    public static int calculate(List<String> notation) {
        Stack<String> stack = new Stack<>();
        for (String s : notation) {
            if (s.matches("\\d+")) {
                stack.push(s);
            } else {
                int num1 = Integer.parseInt(stack.pop());
                int num2 = Integer.parseInt(stack.pop());
                int result = 0;
                switch (s) {
                    case "+":
                        result = num1 + num2;
                        break;
                    case "-":
                        result = num2 - num1;
                        break;
                    case "*":
                        result = num1 * num2;
                        break;
                    case "/":
                        result = num2 / num1;
                        break;
                    default:
                        break;
                }
                stack.push("" + result);
            }
        }
        return Integer.parseInt(stack.pop());
    }

    //reversePolishNotation用 空格隔开
    public static List<String> getListString(String reversePolishNotation) {
        String[] array = reversePolishNotation.split(" ");
        return Arrays.asList(array);
    }
}


猜你喜欢

转载自blog.csdn.net/weixin_42413454/article/details/92016705
今日推荐