四方显神

导航

数据结构007_中缀转后缀表达式

中缀表达式转后缀表达式思路:

1.初始化两个栈:运算符栈S1和储存中间结果的栈S2;

2.从左到右扫描中缀表达式

3.遇到操作数时,将其压入S2;

4.遇到运算符,比较其与S1栈顶运算符的优先级:

  • 如果S1为空,或栈顶运算符是左括号 '(' ,则直接将此运算符入栈;
  • 若优先级比栈顶运算符的高,也将运算符压入S1;
  • 若优先级没有S1栈顶优先级高,将S1栈顶的运算符弹出并压入S2中,再次与S1中新的栈顶运算符进行比较。

5.遇到括号时:

  • 如果是左括号 '(' ,直接入栈S1;
  • 如果是右括号,依次弹出S1栈顶的运算符,并压入S2,直到遇到左括号,此时将这一对括号丢弃;

6.重复不准走2-5,直到表达式最右边

7.将S1中剩余的运算符依次弹出并压入S2;

8.依次弹出S2中元素并输出,结果的逆序即为中缀表达式对应的后缀表达式

代码:

package com.njcx.test3;

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

public class ToPolandExp {
    /**
     * 完成将中缀表达式转后缀表达式的功能 因为直接对string进行操作不方便, 因此先将"1+((20+3)*4)-5" 放入中缀表达式对应的list
     * 即arrayList[1,+,(,(,20,+,3,),*,4,),-,5,]
     */
    public static void main(String[] args) {
        String expression = "1+((2+3)*4)-5";
        List<String> list = toInfixExpressionList(expression);
        System.out.println("转换后的中缀表达式:" + list);

        List<String> ls = parseSuffixExpressionList(list);
        System.out.println("转换后的后缀表达式:" + ls);
    }

    /**
     * 将中缀表达式转成对应的list
     */
    public static List<String> toInfixExpressionList(String s) {
        // 定义一个list存放中缀表达式对应的内容
        List<String> list = new ArrayList<String>();
        int i = 0; // 这是一个指针,用于遍历中缀表达式字符串
        String str;// 做对多位数的拼接工作
        char c;// 每遍历一个字符就放入ch中
        do {
            // 如果ch是一个非数字,就需要加入到list中 48(0) 57(9)
            if ((c = s.charAt(i)) < 48 || (c = s.charAt(i)) > 57) {
                list.add("" + c);
                i++;// i 要后移
            } else { // 如果是一个数需要考虑多位数
                str = ""; // 先将str置成空串
                while (i < s.length() && ((c = s.charAt(i)) >= 48 && (c = s.charAt(i)) <= 57)) {
                    str += c;// 拼接
                    i++;
                }
                list.add(str);
            }

        } while (i < s.length());
        return list;
    }

    /**
     * 将中缀表达式转换成后缀表达式
     * 
     * @param ls
     *            存放中缀表达式的列表,也是由上面的方法转换来哒
     * @return
     */
    public static List<String> parseSuffixExpressionList(List<String> ls) {
        // 注意哦,这里s2不用另一个栈了(因为s2全程也没有pop操作而且后续需要逆序,比较麻烦),
        // 直接用list作为s2,后面输出就是逆波兰表达式,不需要倒序
        Stack<String> s1 = new Stack<String>();// 运算符栈
        List<String> s2 = new ArrayList<String>(); // 存放中间结果的列表
        for (String item : ls) {
            if (item.matches("\\d+")) {
                // 如果是一个数字,加入s2
                s2.add(item);
            } else {
                // 如果是符号就多了,),(,+-*/
                if (item.equals("("))
                    s1.push(item);
                else if (item.equals(")")) {
                    while (!s1.peek().equals("(")) { // 这里怎么会报错啊,按道理有右括号一定有左括号啊
                        // 如果s1栈顶运算符不是"(",就要一直把运算符pop出来放进s2里
                        s2.add(s1.pop());
                    }
                    s1.pop();// 这是丢掉"(",至此这对括号消除了
                } else {
                    // 如果是加减乘除就要和s1栈顶运算符比较优先级了,这里再编写一个类Operation可以返回运算符对应的优先级
                    if (s1.size() != 0 && Operation.getValue(item) < Operation.getValue(s1.peek()))
                        s2.add(s1.pop());
                    s1.push(item);
                }
            }
        }
        // 判断完了,将s1中剩下的运算符弹出,依次进入s2
        while (s1.size() != 0)
            s2.add(s1.pop());
        return s2;// 注意因为是存放到List, 因此按顺序输出就是对应的后缀表达式对应的List
    }

}

/**
 * 编写一个类可以返回运算符对应的优先级
 * 
 * @author 抱金子
 *
 */
class Operation {
    private static int add = 1;
    private static int sub = 1;
    private static int mul = 2;
    private static int div = 2;

    public static int getValue(String operation) {
        int val = 0;
        switch (operation) {
        case "+":
            val = add;
            break;
        case "-":
            val = sub;
            break;
        case "*":
            val = mul;
            break;
        case "/":
            val = div;
            break;
        default:
            break;
        }
        return val;
    }
}

 

posted on 2020-09-21 22:15  szdbjooo  阅读(258)  评论(0)    收藏  举报