X16数据结构部分04

本文详细介绍了将中缀表达式转换为后缀表达式的思路和方法,包括关键的辅助过程和完整的Java实现代码。通过理解这个转换过程,可以深入掌握数据结构与算法中的操作技巧。

中缀表达式转后缀表达式实现思路

		/*
        中缀表达式
        转后缀表达式
        思路分析
        比较麻烦
        需要耐心分析

        案例
        1 + ( ( 2 + 3 ) * 4 ) - 5
        预期结果:16
         */

        /*
        详细步骤
        1. 创建两个栈,一个存放运算符,一个存放中间结果,中间结果就是计算过后的数字栈
        2. 从左至右扫描中缀表达式
        3. 遇到数字时,压入栈s2
        4. 遇到运算符时,比较与栈顶运算符的优先级
            a. 栈顶为空或栈顶为左括号,直接将该运算符入栈1
            b. 优先级高于栈顶元素,也将运算符压入s1栈中
            c. 否则,如果栈顶是小括号类的非运算符,压入栈s1
               如果优先级一样,直接弹出s1栈顶元素,并压入s2中,并重新回到a的判断
               我认为这里是算法实现的关键
        5. 遇到括号时
            a. 左括号直接入栈
            b. 右括号的话,依次弹出s1的运算符,直到遇到左括号为止
               再把左括号弹出,做完这些步骤后继续循环
        6. 扫描结束后,将s1剩余运算符依次弹出并压入s2
        7. 依次弹出s2元素并输出,结果的逆序即为中缀表达式对应的后缀表达式

		还有一个人工中缀转后缀
            后缀:把运算符号移动到对应的括号后面,然后再去掉小括号
         */

中缀转后缀辅助方法

	/**
     * 字符串表达式转ArrayList集合
     * @param string 字符串表达式
     * @return ArrayList集合
     */
    public static List<String> stringExpressionToArrayList(String string){  // 1+((2+3)*4)-5
        /*
        初始化数据
         */
        List<String> stringList = new ArrayList<>();   // 定义结果集
        String str;     // 多位数拼接
        int index = 0;  // 遍历字符串
        char c;         // 遍历到的字符
        do {
            if ((c = string.charAt(index)) < 48 || (c = string.charAt(index)) > 57){
                /*
                程序运行到此处
                说明c不是一个数字
                直接加入stringList集合就行
                 */
                stringList.add("" + c);
                index++;
            }else{
                /*
                程序运行到此处
                说明c是一个数字
                这个时候需要考虑多位数
                并且需要判断后一位是否
                已经走到了表达式最后
                 */
                str = "";
                while (index < string.length() && (c = string.charAt(index)) >= 48 && (c = string.charAt(index)) <= 57){
                    /*
                    程序运行到此处
                    说明是多位数
                    需要进行拼接
                     */
                    str += c;
                    index++;
                }
                /*
                程序运行到此处
                说明拼接完毕
                或者说本来就是1位数
                直接加进去就行
                 */
                stringList.add(str);
            }
        }while (index < string.length());
        /*
        程序运行到此处
        说明扫描完毕
        直接返回集合即可
         */
        return stringList;
    }

中缀转后缀完整代码

package dc;

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

/**
 * @author 404小恐龙
 * @version 1.8
 * @date 2021/10/8 15:04
 */
public class d19 {
    /*
        详细步骤
        1. 创建两个栈,一个存放运算符,一个存放中间结果,中间结果就是计算过后的数字栈
        2. 从左至右扫描中缀表达式
        3. 遇到数字时,压入栈s2
        4. 遇到运算符时,比较与栈顶运算符的优先级
            a. 栈顶为空或栈顶为左括号,直接将该运算符入栈1
            b. 优先级高于栈顶元素,也将运算符压入s1栈中
            c. 否则,如果栈顶是小括号类的非运算符,压入栈s1
               如果优先级一样,直接弹出s1栈顶元素,并压入s2中,并重新回到a的判断
               我认为这里是算法实现的关键
        5. 遇到括号时
            a. 左括号直接入栈
            b. 右括号的话,依次弹出s1的运算符,直到遇到左括号为止
               再把左括号弹出,做完这些步骤后继续循环
        6. 扫描结束后,将s1剩余运算符依次弹出并压入s2
        7. 依次弹出s2元素并输出,结果的逆序即为中缀表达式对应的后缀表达式
         */
    public static void main(String[] args) {
        /*
        中缀表达式
        转后缀表达式

        案例
        1+((2+3)*4)-5
        预期结果:1 2 3 + 4 * + 5 -

        代码实现注意点
            由于对字符串操作不太方便,所以先转成ArrayList集合的形式
         */
        List<String> stringList = stringExpressionToArrayList("1+((2+3)*4)-5");
        System.out.println(stringList); // [1, +, (, (, 2, +, 3, ), *, 4, ), -, 5]
        List<String> stringList1 = convertInfixExpressionToPostfixExpression(stringList);
        System.out.println(stringList1); // [1, 2, 3, +, 4, *, +, 5, -]
    }

    /**
     * 中缀表达式转后缀表达式
     * @param stringList 中缀表达式对应List集合
     * @return 后缀表达式对应List集合
     */
    public static List<String> convertInfixExpressionToPostfixExpression(List<String> stringList){
        /*
        初始化数据
        定义两个栈
        一个存放运算符
        一个存放结果

        但由于结果栈从未弹栈
        并且最后还需要逆序输出
        所以完全可以用ArrayList替代
         */
        Stack<String> operatorStack = new Stack<>();
        List<String> resultStack = new ArrayList<>();
        /*
        程序核心部分
        扫描遍历stringList
         */
        for (String s : stringList) {
            if (s.matches("\\d+")){
                /*
                程序运行到此处
                说明集合元素是一个数字
                直接入栈
                 */
                resultStack.add(s);
            }else if (s.equals("(")){
                /*
                程序运行到此处
                说明扫描到左括号
                直接入栈
                 */
                operatorStack.push(s);
            }else if (s.equals(")")){
                /*
                程序运行到此处
                说明扫描到的是右括号
                现在依次弹出运算符栈的元素
                 */
                while(!operatorStack.peek().equals("(")){
                    /*
                    程序运行到此处
                    说明还没看到左括号
                    这个时候继续弹栈
                     */
                    resultStack.add(operatorStack.pop());
                }
                /*
                程序运行到此处
                说明看到了左括号
                弹出左括号
                 */
                operatorStack.pop();
            }else {
                /*
                程序运行到此处
                说明扫描到运算符
                需要做优先级判断
                 */
                while (operatorStack.size() != 0 && OperatorPrecedence.getPriorityNumber(operatorStack.peek()) >= OperatorPrecedence.getPriorityNumber(s)){
                    /*
                    程序运行到此处
                    说明栈顶优先级高于或等于当前优先级
                    此时需要弹出s1栈顶元素并加入到s2
                    完成此操作后继续重复同样操作
                     */
                    resultStack.add(operatorStack.pop());
                }
                /*
                程序运行到此处
                说明栈顶优先级低于当前优先级
                或者说符号栈为空
                这个时候直接压栈
                 */
                operatorStack.push(s);
            }
        }
        /*
        程序运行到此处
        说明第1轮扫描完毕
        这时需要将符号栈剩余的操作符
        加入结果集当中
         */
        while (operatorStack.size() != 0){
            resultStack.add(operatorStack.pop());
        }
        /*
        程序运行到此处
        说明已经处理好了
        直接返回结果
         */
        return resultStack;
    }

    /**
     * 字符串表达式转ArrayList集合
     * @param string 字符串表达式
     * @return ArrayList集合
     */
    public static List<String> stringExpressionToArrayList(String string){  // 1+((2+3)*4)-5
        /*
        初始化数据
         */
        List<String> stringList = new ArrayList<>();   // 定义结果集
        String str;     // 多位数拼接
        int index = 0;  // 遍历字符串
        char c;         // 遍历到的字符
        do {
            if ((c = string.charAt(index)) < 48 || (c = string.charAt(index)) > 57){
                /*
                程序运行到此处
                说明c不是一个数字
                直接加入stringList集合就行
                 */
                stringList.add("" + c);
                index++;
            }else{
                /*
                程序运行到此处
                说明c是一个数字
                这个时候需要考虑多位数
                并且需要判断后一位是否
                已经走到了表达式最后
                 */
                str = "";
                while (index < string.length() && (c = string.charAt(index)) >= 48 && (c = string.charAt(index)) <= 57){
                    /*
                    程序运行到此处
                    说明是多位数
                    需要进行拼接
                     */
                    str += c;
                    index++;
                }
                /*
                程序运行到此处
                说明拼接完毕
                或者说本来就是1位数
                直接加进去就行
                 */
                stringList.add(str);
            }
        }while (index < string.length());
        /*
        程序运行到此处
        说明扫描完毕
        直接返回集合即可
         */
        return stringList;
    }
}

/**
class OperatorPrecedence
return precedence of operator

 @author 404 little dinosaur
 */
class OperatorPrecedence{
    private static int ADD = 1;
    private static int SUB = 1;
    private static int MUL = 2;
    private static int DIV = 2;

    public static int getPriorityNumber(String operation){
        int result = 0;
        switch (operation){
            case "+":
                result = ADD;
                break;
            case "-":
                result = SUB;
                break;
            case "*":
                result = MUL;
                break;
            case "/":
                result = DIV;
                break;
            default:
                break;
        }
        return result;
    }
}
/*
code structure
d19
    main
    convertInfixExpressionToPostfixExpression 
    stringExpressionToArrayList
OperatorPrecedence
    getPriorityNumber
    ADD
    SUB
    MUL
    DIV
 */

总目录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

muskfans

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值