• 栈 之 求后缀表达式


    最近学习了栈,为了巩固知识,照着书实现了一个有关于栈的应用的例子:将中缀表达式转化为后缀表达式。

    这里先来明白什么是中缀表达式:我们正常使用的算式,如a + b * c 就是一个中缀表达式。中缀表达式的特点就是运算符在中间。

    后缀表达式就是 运算符在后面,像上面的式子如果转化为后缀表达式就为  a b * + 。

    这里以测试用例:A*B(B+C)-D/(E+F) 来为大家介绍一下转化的过程。

    由中缀表达式中读取的字符

    分解中缀表达式的过程

    求后缀表达式的过程

    栈中的内容

    规则

    A

    A

    将操作数A写至后缀(后缀表达式)

    *

    A*

    A

    *

    若栈为空,将*进栈

    (

    A*(

    A

    *(

    将操作数(入栈

    B

    A*(B

    AB

    *(

    将操作数B写入后缀

    +

    A*(B+

    AB

    *

    栈非空,故弹出一项

     

    A*(B+

    AB

    *(

    有(,故将(进栈

     

    A*(B+

    AB

    *(+

    将操作数+进栈

    C

    A*(B+C

    ABC

    *(+

    将操作数C写入后缀中

    )

    A*(B+C)

    ABC+

    *(

    遇见),弹出栈中的位于(之后的内容即+,写至后缀

     

    A*(B+C)

    ABC+

    *

    若有(,直接将其出栈

    -

    A*(B+C)

    ABC+*

    -

    将*出栈,写入后缀,再将-进栈

    D

    A*(B+C)-D

    ABC+*D

    -

    将D写入后缀

    /

    &-D/

    &D

    -/

    将进栈

    (

    &-D/(

    &D

    -/(

    将(入栈

    E

    &-D/(E

    &DE

    -/(

    将E写入后缀

    +

    &-D/(E+

    &DE

    -/

    栈弹出一项

     

    &-D/(E+

    &DE

    -/(

    出栈的为(,因此将其重新进栈

     

    &-D/(E+

    &DE

    -/(+

    将+进栈

    F

    &-D/(E+F

    &DEF

    -/(+

    将F写入后缀

    )

    &-D/(E+F)

    &DEF

    -/(

    遇见),弹出栈中的位于(之后的内容即+,写至后缀

     

    &-D/(E+F)

    &DEF+

    -/

    遇见(,将其出栈

     

    &-D/(E+F)

    &DEF+/-

    将剩下栈中的元素全部出栈,写入后缀

    A*(B+C)-D/(E+F)

    如果大家肯定还不太明白,大家可以自己百度一下,这里就不多做介绍了。

    实现的算法就是上面的转化过程,下面是源码,包含解释:

    1.栈类stackX

    package infix;
    /*
     * 这是一个自己定义的,存储数据的栈
     */
    public class StackX {
        private int maxSize;
        private char[] stackArray;
        private int top;
        
        public StackX(int s){
            maxSize = s;
            stackArray = new char[maxSize];
            top = -1;
        }
        //入栈操作
        public void push(char value){
            stackArray[++top] = value;
        }
        //出栈操作
        public char pop(){
            return stackArray[top--];
        }
        //查看栈顶元素
        public char peek(){
            return stackArray[top];
        }
        //判断是是否为空
        public boolean isEmpty(){
            return (top == -1);
        }
        public int size(){
            return top+1;
        }
        //查看在位置n的元素
        public char peekN(int n){
            return stackArray[n];
        }
        //打印从栈底到栈顶的元素
        public void displayStack(String s){
            System.out.print(s);
            System.out.print("Stack (bottom-->top):");
            for (int j = 0; j < size(); j++) {
                System.out.print(peekN(j));
                System.out.print(' ');
            }
            System.out.println("");
        }
    }

     2.InToPost类,存放的操作方法

    package infix;
    
    public class InToPost {
        private StackX stack;
        private String input;
        private String output="";
        
        public InToPost(String in){
            input = in;                        //输入的要分析的字符串
            int stackSize = input.length();
            stack = new StackX(stackSize);
        }
        /*
         * 将中缀表达式转化为后缀表达式
         * 如果读取的单个字符不是基础运算符,则将这个字符放入output中。output中的数据只会增加,不会变化
         */
        public String doTrans(){
            
            for (int i = 0; i < input.length(); i++) {
                char ch = input.charAt(i);   //从input中取出第i个字符
                stack.displayStack("For " + ch + " ");        //调用StackX中的方法来显示ch
                switch (ch) {
                case '+':
                case '-':
                    gotOper(ch, 1);
                    break;
                case '*':
                case '/':
                    gotOper(ch, 2);
                    break;
                case '(':
                    stack.push(ch);
                    break;
                case ')':
                    gotParen(ch);
                    break;
                default:
                    output = output + ch;
                    break;
                }
            }
            //将剩余的栈中元素全部出栈。出栈的顺序就代表了运算的顺序。
            while(!stack.isEmpty()){
                stack.displayStack("While ");
                output = output + stack.pop();
            }
            stack.displayStack("End  ");
            return output;
        }
        
        public void gotOper(char opThis, int prec1){
            while (!stack.isEmpty()) {       //循环将栈中的char类型出栈
                char opTop = stack.pop();
                if (opTop == '(') {            
                    stack.push(opTop);        //将出栈的‘(’元素进栈
                    break;
                }else {
                    int prec2;
                    //判断onTop的优先级
                    if (opTop=='+'||opTop == '-') {        //设置加减的优先级为1
                        prec2 = 1;
                    }else {                                //其他的优先级为2
                        prec2 = 2;
                    }
                    if (prec2 < prec1) {        //当传入的onThis的优先级prec1大于出栈的opTop的优先级
                        stack.push(opTop);      //将出栈的opTop进栈
                        break;
                    }else {
                        output = output + opTop;    //如果出栈的opTop的算术优先级比opThis的大,则将其放到output中
                    }
                }
            }
            stack.push(opThis);
        }
        public void gotParen(char ch){
            while (!stack.isEmpty()) {
                char chx = stack.pop();        //读取到‘(’,就出栈在‘(’和‘)’之间的所有元素
                if (chx == '(') {
                    break;
                }else {
                    output = output + chx;        //如果读到了‘)’,则将stack栈中的符号放入output中
                }
            }
        }
    }

    3.主类:

    package infix;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    /*
     * 用栈来实现把一个中缀表达式,转化为一个后缀表达式
     */
    public class InfixApp {
        public static void main(String[] args) throws IOException {
            String input,output;
            while(true){
                System.out.println("输入要运算式: ");
                System.out.flush();            
                input = getString();
                if (input.equals("")) {
                    System.out.println("输入不要为空");
                    break;
                }
                //创建InToPost对象
                InToPost theTrans = new InToPost(input);
                //调用doTrans方法
                output = theTrans.doTrans();
                System.out.println("转化后的运算式为: " + output + '
    ');
            }
        }
        //用于读取输入流中的数据
        public static String getString() throws IOException{
            InputStreamReader in = new InputStreamReader(System.in);
            BufferedReader buffer = new BufferedReader(in);
            String s = buffer.readLine();
            return s;
        }
    }

     运行结果:

    输入要运算式: 
    A*(B+C)-D/(E+F)
    For A Stack (bottom-->top):
    For * Stack (bottom-->top):
    For ( Stack (bottom-->top):* 
    For B Stack (bottom-->top):* ( 
    For + Stack (bottom-->top):* ( 
    For C Stack (bottom-->top):* ( + 
    For ) Stack (bottom-->top):* ( + 
    For - Stack (bottom-->top):* 
    For D Stack (bottom-->top):- 
    For / Stack (bottom-->top):- 
    For ( Stack (bottom-->top):- / 
    For E Stack (bottom-->top):- / ( 
    For + Stack (bottom-->top):- / ( 
    For F Stack (bottom-->top):- / ( + 
    For ) Stack (bottom-->top):- / ( + 
    While Stack (bottom-->top):- / 
    While Stack (bottom-->top):- 
    End  Stack (bottom-->top):
    转化后的运算式为: ABC+*DEF+/-
    
    输入要运算式:
  • 相关阅读:
    unicode字符集
    534,rgba()和opacity的透明效果有什么不同?
    1004,js中的fliter
    1003,js array map()方法
    JavaScript 数据类型和数据结构
    JavaScript实现浮点数运算问题
    Chrome浏览器不能正确加载更新后JavaScript和Css文件原因及解决方法
    MySQL安装版与压缩版安装方法
    VUE列表渲染 FOR-IN和FOR-OF的区别
    for、for-in、for-of、forEach的区别
  • 原文地址:https://www.cnblogs.com/mercuryli/p/5011151.html
Copyright © 2020-2023  润新知