《数据结构与算法》(一) 基于JAVA栈 实现中缀表达式后缀表达式互相转换

中缀表达式转后缀表达式

一、原理概述:

a.定义一个栈用于存放运算符,以及 括号 “[()]” 操作符
b.定义一个字符串result用于接收计算结果
c.从表达式第一个字符开始作为判断位; 判断位,用于与栈顶元素对比优先级,从而确定:将判断位入栈 或者 将栈顶元素弹出
d.遇到操作数作为判断位,直接将其作为结果添加到result的末尾;
e.如果碰到判断位是操作符,当栈为空时直接将其入栈,表达式下一位作为判断位;栈不为空时,比较判断位与栈顶的元素的优先级;
f.如果 判断位的优先级 >= 栈顶元素的优先级,判断位入栈成为新栈顶,表达式下一位成为判断位;
g.如果 判断位的优先级 < 栈顶元素的优先级,弹出栈顶元素(运算符打印到结果,括号忽略),栈顶元素更新,判断位不变,继续对比新的栈顶与判断位,,,,直至结束;

需要注意的是:

  1. 针对左括号 ( [ ,他们的优先级不是固定的;
  2. 当他们作为判断位与栈顶元素对比时,他们是最高的;
  3. 当他们作为栈顶元素与判断位对比时,他们的优先级是最低的;

作为判断位时:

  • 判断它是否入栈的优先级:
  • 在这里插入图片描述

作为栈顶元素:

* 判断栈顶元素是否出栈的优先级: *****    等于    **/**    大于   **+**    等于    **-**    大于   **(**   等于   **)**   大于   **[**   等于   **]**
PS*考验视力的时候了,,,,

二、案例以及具体栈操作:

  • 定义栈:X = {} ,从右到左表示栈底到栈顶

  • 定义打印结果:result = “”;

  • 定义表达式:F = a + c * [ b * (c + d) + g ]

1.a是操作数,输出,打印到输出结果;

X = {}   result = "a";                   F = a + c * [ b * (c + d) + g ]

2.“+” 是操作符,入栈;

X = {+}   result = "a";                  F = a + c * [ b * (c + d) + g ]

3.c 是操作数,输出;

X = {+}   result = "ac";                  F = a + c * [ b * (c + d) + g ]

4.“*”是操作符,优先级大于等于当前栈顶“+”,“*” 入栈;

X = {+,*}   result = "ac";                F = a + c * [ b * (c + d) + g ]

5."[" 特殊符号,《判断入栈时视为最高优先级,判断出栈时视为最低优先级》,此时判断它是否需要入栈,此时优先级最高,大于等于当前栈顶"*",所以入栈;

X = {+,*,[}   result = "ac";              F = a + c * [ b * (c + d) + g ]

6.b为操作数,输出;

X = {+,*,[}   result = "acb";             F = a + c * [ b * (c + d) + g ]

7.”*“ 操作符,此时栈顶为 ”[“ ,需要根据优先级判断是否需要将当前栈顶出栈,那么 ”[“ 优先级最低,”*“ 高于栈顶的 ”[“ 《特殊符号入栈》;

X = {+,*,[,*}   result = "acb";           F = a + c * [ b * (c + d) + g ]

8.”(“ 入栈 《特殊符号,它作为入栈判断位,视为次高优先级,当它是栈顶元素时,视为次低优先级》,此时它需要入栈;

X = {+,*,[,*,(}   result = "acb";         F = a + c * [ b * (c + d) + g ]

9.操作数 c 输出到result ;

X = {+,*,[,*,(}   result = "acbc";        F = a + c * [ b * (c + d) + g ]

10."+" 操作符,此时 ”(“ 作为栈顶,优先级小于 ”+“ 那么 “+” 入栈;

X = {+,*,[,*,(,+}   result = "acbc";      F = a + c * [ b * (c + d) + g ]

11.操作数d ,输出;

X = {+,*,[,*,(,+}   result = "acbcd";     F = a + c * [ b * (c + d) + g ]

12.")" 操作符,优先级低于任意运算符 《 + - * / 》, 等于与它配对的 “(” 那么此时,它小于当前栈顶 “+”,当前栈顶出栈,并输出;

X = {+,*,[,*,(}   result = "acbcd+";      F = a + c * [ b * (c + d) + g ]

13.当前栈顶变为:“(” 优先级等于“)” 括号不需要打印到输出结果,所以直接出栈,当前判断位 “)” 也舍弃;

X = {+,*,[,*}   result = "acbcd+";         F = a + c * [ b * (c + d) + g ]

14.新的判断位,变成“+” 它的优先级小于当前栈顶 “*” ,所以当前栈顶运算符,出栈并输出;

X = {+,*,[}   result = "acbcd+*";           F = a + c * [ b * (c + d) + g ]

15.新栈顶:“[” ,作为栈顶时,它优先级最低,等于与他配对的 “]” , 当前判断位 “+” 优先级大于栈顶的 “[” 所以需要入栈;

X = {+,*,[,+}   result = "acbcd+*";         F = a + c * [ b * (c + d) + g ]

16.”+“ 入栈后下一个判断位是操作数 g,直接输出;

X = {+,*,[,+}   result = "acbcd+*g";        F = a + c * [ b * (c + d) + g ]

17.g 输出后,新判断位 ”]“ , 它的优先级小栈顶”+“ 所以栈顶”+“ 出栈并输出;

X = {+,*,[}   result = "acbcd+*g+";          F = a + c * [ b * (c + d) + g ]

18.新栈顶”[“ 优先级等于判断位”]“ 且他们配对,由于括号不用打印到输出结果,所以同时舍弃;

当F 表达式走到结尾,且栈内还有操作符时,那么需要将栈中所有的运算符按序出栈,并输出到结果:" 括号只出栈,不输出到结果 ";

最终得到后缀表达式:

X = {}   result = "acbcd+*g+*+";
  • 大致逻辑如上,上面的逻辑是没有问题的,按照所述逻辑去实现代码应该问题不大;

三、代码以及实现:

import java.util.Stack;
public class InfixToSuffix {
    public static void main(String[] args){
        String formula = "a+b+[c*(d-f)+g]*h";
        //formula = "a+b*(c+d+e)+g*h";
        //formula = "a+c*[b*(c-d)+g]";
        //formula = "b*(c+d+e)";
        System.out.println(infixToSuffix(formula.toCharArray()));
    }
    public static String infixToSuffix(char[] formula){
        StringBuilder result = new StringBuilder();
        Stack<Character> formulaStack = new Stack<>();
        boolean isPush = true;// 标记上一次循环,栈的操作是入栈还是出栈
        boolean isEnd = false;// 表达式最后一位是否已经处理完成
        int index = 0;// 标记当前判断位的位置
        int current;// 当前判断位优先级
        int top ;   // 栈顶元素优先级
        while(index < formula.length){
            current = formateChar(formula[index]);
            if (!formulaStack.isEmpty()) top = formateChar(formulaStack.peek());  else  top = 0;
            if (index == formula.length - 1){// 表达式已经判断完成,栈中所有操作符出栈并输出到结果
                if (current < 0 && !isEnd) { //表达式最后一位为操作数
                    result.append(formula[index]);
                    isEnd = true;
                }
                if (!formulaStack.isEmpty()){ //将栈中非括号操作符出栈并输出
                    char end = formulaStack.pop();
                    if("[(".indexOf(end) < 0)
                        result.append(end);
                } else  { // 栈空,退出
                    index ++;
                }
            } else {
                if ((top - current == 90 || top - current == 100)){// 左括号与右括号匹配,同时舍弃
                    index++;
                    formulaStack.pop();
                } else if (current < 0){//数字直接输出到结果
                    result.append(formula[index]);
                    index++;
                } else if (!formulaStack.isEmpty() && current > 0) {
                    //判断位不是数字,栈不空,那么对比栈顶元素与当前判断位的优先级
                    if (current > top){栈顶优先级小于当前判断字符
                        formulaStack.push(formula[index]); //top = current;
                        index ++;
                        isPush = true;
                    } else if (top > current){//栈顶优先级大于当前判断字符
                        if (top > 90){ // 出栈时关于括号的优先级反转:最高->最低  次高 -> 次低
                            formulaStack.push(formula[index]); //top = current;
                            index ++;
                            isPush = true;
                        } else {
                            result.append(formulaStack.pop()); //top = formulaStack.peek();//栈顶元素出栈
                            isPush = false;
                        }
                    }else if (current == top){//栈顶元素优先级等于当前判断位字符的优先级
                        if (isPush){ // 上次循环栈的操作是入栈,那么优先级相等入栈
                            formulaStack.push(formula[index]);//top = current;
                            index ++;
                        } else {// 上次循环栈的操纵是出栈,此时优先级相等也出栈
                            result.append(formulaStack.pop()); //top = formulaStack.peek();//栈顶元素出栈
                        }
                    }
                } else if (formulaStack.isEmpty() && current > 0){ // 栈空,且当前判断位是操作符,那么直接入栈
                    formulaStack.push(formula[index]);
                    index ++;
                }
            }
        }
        return result.toString();
    }
    public static int  formateChar(char a){//设置优先级(是否进栈)
        if ("[".indexOf(a) >= 0)           return  101; //出栈优先级最低 101 - 1 = 100  [和] 配对
        else if ("(".indexOf(a) >= 0)      return   92; //出栈优先级次低  92 - 2 =  90  (和) 配对
        else if ("*/".indexOf(a) >= 0)     return    4;
        else if ("-+".indexOf(a) >= 0)     return    3;
        else if (")".indexOf(a) >= 0)      return    2;
        else if ("]".indexOf(a) >= 0)      return    1;
        else if (" ".indexOf(a) >= 0)      return    0; //栈空时栈顶的优先级 
        else                               return   -1; //操作数优先级最低
    }
}

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

一、原理概述:

  • a.从后缀表达式第一个元素开始,遇到操作数(数字),即压入栈中;
  • b.遇到操作符则弹出当前栈最顶上的两个数字进行运算,并将结果压入栈中;
  • c.按照上述规律直至后缀表达式遍历完成,最后栈中只剩下一个表达式即为计算结果;

由于操作简单就不再赘述了。

二、代码实现

public static String suffixToInfix(char[] suffixs){
        String TEMP = "";
        Stack<String> suffixStack = new Stack<>();
        
        int lastAdd = 0;
        int index = 0;
        int current;
        while (index < suffixs.length){
            current = formateChar(suffixs[index]);
            if (current < 0){ // 数字直接入栈
                suffixStack.push("" + suffixs[index]);
                 index++;
            } else if (current == 3){ // + 或 - 操作符,
                TEMP = suffixs[index] + suffixStack.pop();
                TEMP = suffixStack.pop() + TEMP;
                index++;
                suffixStack.push(TEMP);
                lastAdd = 1;
            } else if (current == 4){ // * 或 / 运算符
                if (lastAdd != -1){ // 上一步运算不是乘法,需要用括号,保证优先级
                    TEMP = suffixs[index] + "(" +  suffixStack.pop() + ")";
                    TEMP = suffixStack.pop() + TEMP;    
                } else { // 上一步计算也是乘法,优先级可以得到保证
                    TEMP = suffixs[index] + suffixStack.pop();
                    TEMP = suffixStack.pop() + TEMP;
                }
                index++;
                suffixStack.push(TEMP);
                lastAdd = -1;
            }
        }
        
        
        
        return  suffixStack.pop();
    }
    
    public static int  formateChar(String a){
        if ("*/".indexOf(a) >= 0)     return  4;
        else if ("-+".indexOf(a) >= 0)     return  3;
        else if (" ".indexOf(a) >= 0)      return  0;
        else                               return -1;//字母 或表达式 
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值