DS03-02前缀、中缀、后缀表达式

本文介绍了前缀、中缀和后缀表达式的基本概念,以及如何进行中缀表达式到后缀表达式的转换。通过具体的代码示例展示了中缀表达式的计算和后缀表达式的求值过程。此外,还提供了中缀表达式转化为List字符串的方法。这些知识对于理解计算表达式和设计简单的解析器至关重要。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

5.前缀、中缀、后缀表达式

5.1 前缀表达式
  • 从右至左扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算(栈顶元素 和 次顶元素),并将结果入栈;重复上述过程直到表达式最左端,最后运算得出的值即为表达式的结果

  • 中缀表达式转化为前缀表达式的例子:

    a+b ---> +,a,b

    a+(b-c) ---> +,a,-,b,c

    a+(b-c)*d ---> +,a,*,-,b,c,d

    a+1+3 ---> +,+,a,1,3

5.2 中缀表达式

1)中缀表达式就是常见的运算表达式.按照人们的顺序来的

代码
package 自己写.栈计算机器;

import java.util.Stack;

public class CalStack {
    public static void main(String[] args) {

//        String str = "15-6+1*66+88";//5
                String str = "15-6+1*66+88";//13

        Stackcal numStack = new Stackcal(10);
        Stackcal signStack = new Stackcal(10);



        int pop1,pop2,rs;
        String keepNum = "";
        for (int i = 0; i < str.length(); i++) {
            int a = 0;
            char curSign = str.charAt(i);
            if(curSign <=57 && curSign >= 48){
                    //单位数字
//                    numStack.push(str.charAt(i) - 48);

                keepNum += curSign;
                //如果ch已经是expression的最后一位,就直接入栈
                if(i == str.length() - 1){
                    numStack.push(Integer.parseInt(keepNum));
                }else {
                    if(str.charAt(i+1)<=57 && str.charAt(i+1)>=48){

                    }else {
                        numStack.push(Integer.parseInt(keepNum));
                        keepNum = "";
                    }
                }
            }else {
                    if(signStack.ifEmpty()){
                        signStack.push(curSign);
                    }else {
                        int preSign = signStack.pop();
                        if(signStack.compareBig(preSign) < signStack.compareBig(curSign)){
                                signStack.push(preSign);
                                signStack.push(curSign);
                            }else {
                                pop1 = numStack.pop();
                                pop2 = numStack.pop();
                                rs = numStack.consult(pop1,pop2,preSign);
                                numStack.push(rs);
                                signStack.push(curSign);
                            }
                    }
                }
        }
        while (signStack.ifEmpty() == false){
            pop1 = numStack.pop();
            pop2 = numStack.pop();
            int sign = signStack.pop();
            rs = numStack.consult(pop1,pop2, (char) sign);
            System.out.println(rs);
            numStack.push(rs);
        }
        System.out.println(numStack.pop());

    }
}

    class Stackcal{
        private int maxSize;//栈的大小
        private int[] stack;//数组,模拟栈,数据放在该数组
        private int top = -1;//top表示栈顶,初始化为-1

        public Stackcal(int maxSize) {
            this.maxSize = maxSize;
            stack = new int[this.maxSize];
        }


        public int getTop(){
            return top;
        }

        /**
         * 比较字符串的大小
         * @return
         */

        public int  compareBig(int c){
            if(c == '-' || c == '+'){
                return 1;
            }else if(c == '*' || c== '/'){
                return 2;
            }else {
                return -1;
            }
        }

        //栈满
        public boolean ifFull(){
            return top == maxSize - 1;
        }
        //栈空
        public boolean ifEmpty(){
            return top == -1;
        }
        //入栈
        public void push(int value){
            //先判断栈是否满
            if(ifFull()){
                System.out.println("栈满");
                return;
            }
            top++;
            stack[top] = value;

        }
        //出栈
        public int pop(){
            if(ifEmpty()){
                throw new RuntimeException("栈空");
            }
            int value = stack[top];
            top--;
            return value;

        }
        //显示栈的情况[遍历栈],需要从栈顶开始显示数据
        public void list(){
            if(ifEmpty()){
                System.out.println("栈空,没有数据");
                return;
            }
            for (int i = top; i >= 0; i--) {
                System.out.printf("stack[%d] = %d\n" ,i,stack[i]);
            }

        }

        public int  consult(int pop1, int pop2, int preSign) {
            if(preSign == '+'){
                return pop1 + pop2;
            }else if(preSign == '-'){
                return pop2 - pop1;
            }else if(preSign == '/'){
                return pop2 / pop1;
            }else {
                return pop1 * pop2;
            }
        }
    }

5.3 后缀表达式

1)后缀表达式又称逆波兰表达式,与前缀表达式相似,只是运算符位于操作数之后

2)举例说明: (3+4)×5-6 对应的后缀表达式就是 3 4 + 5 × 6

后缀表达式的计算机求值

从左至右扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算(次顶元素 和 栈顶元素),并将结果入栈;重复上述过程直到表达式最右端,最后运算得出的值即为表达式的结果

5.3.1 中缀转List字符串
    /**
     * 中缀转成List字符串
     * @param s
     * @return
     */
    public static List<String> toList(String s){
        //定义一个List,存放中缀表达式,对应的内容
        List<String> ls = new ArrayList<>();
        int i = 0;//指针,用于遍历s;
        String str;//对多位数拼接
        char c;//遍历到一个字符,就放入到c
        do{
            if((c = s.charAt(i)) < 48 || (c = s.charAt(i)) >57){
                ls.add("" + c);
                i++;
            }else {
                str = "";
                while (i < s.length() && (c=s.charAt(i)) > 48 && (c = s.charAt(i)) <=57){
                    str +=c;
                    i++;
                }
                ls.add(str);
            }
        }while (i < s.length());
        return ls;
    }
5.3.2 中缀转后缀表达式
  1. 首先需要初始化两个栈:运算符栈sign1和储存中间结果的栈midn2;

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

  3. 碰见操作数,将其压midn2;

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

    1. 如果sign1为空,或栈顶运算符为左括号“(”,则直接将此运算符入栈;

    2. 否则,若优先级比栈顶运算符的高,也将运算符压入sign1;

    3. 否则,将sign1栈顶的运算符弹出并压入到s2中,再次转到(4-1)与sign1中新的栈顶运算符相比较;

  5. 遇到括号时:
    (1) 如果是左括号“(”,则直接压入sign1
    (2) 如果是右括号“)”,则依次弹出sign1栈顶的运算符,并压入midn2,直到遇到左括号为止,此时将这一对括号丢弃

  6. 重复步骤2至5,直到表达式的最右边

  7. 将sign1中剩余的运算符依次弹出并压入midn2

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

/**
 * 中缀表达式转后缀表达式
 * @param ls
 * @return
 */
public static List<String> parseList(List<String> ls){
    //定义两个栈
    Stack<String> signs = new Stack<>();
    List<String> s2 = new ArrayList<>();
    for (String item :
            ls) {
        if(item.matches("\\d+")){
            s2.add(item);
        }else if(item.equals("(")){
            signs.push(item);
        }else if(item.equals(")")){
            while (!signs.peek().equals("(")){
                s2.add(signs.pop());
            }
            signs.pop();
        }else {
            while (signs.size() != 0 && OperationCompare.getValue(item) <= OperationCompare.getValue(signs.peek())){
                s2.add(signs.pop());
            }
            signs.push(item);
        }
    }

    //
    while (signs.size() != 0){
        s2.add(signs.pop());
    }
    return s2;

}
5.3.3 后缀表达式求值过程

例如: (3+4)×5-6 对应的后缀表达式就是 3 4 + 5 × 6 -

/**
 * 根据后缀表达式返回得数
 * @param ls
 * @return
 */
public static int finalRs(List<String> ls){

    Stack<String> stack = new Stack<>();
    for (String item :
            ls) {
        if (item.matches("\\d+")){
            stack.push(item);
        }else {
            int num2 = Integer.parseInt(stack.pop());
            int num1 = Integer.parseInt(stack.pop());
            int result =0;
            if(item.equals("+")){
                result = num1 + num2;
            }else if(item.equals("-")){
                result = num1 - num2;
            }else if(item.equals("*")){
                result = num1 * num2;
            }else {
                result = num1 / num2;
            }
            stack.push(result+"");
        }
    }
    return Integer.parseInt(stack.pop());
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值