前缀、中缀、后缀表达式

中缀表达式

1、最常见的运算表达式,一般转成后缀表达式

2、求值步骤

(1)创建两个栈,操作符栈 S1、数字栈 S2

(2)从左至右扫描中缀表达式

(3)遇到操作数时,直接入 S2

(4)遇到运算符时,比较其与 S1 栈顶运算符的优先级

1、若 S1 为空或为“(”,直接入栈
2、若优先级 > 栈顶运算符,则入栈
3、若优先级 <= 栈顶运算符,则出栈,并从 S2 先后弹出 a、b,进行运算,即 c = b 运算符 a,并把 c 压入 S2,直到其优先级 > 栈顶运算符优先级时停止或 S1 为空),最后再将其入栈

(5)遇到括号时

1、若为“(”,直接入栈
2、若为“)”,一直出栈并拿 S2 中的栈顶两个元素做相应的运算,从 S2 先后弹出 a、b,进行运算,即 c = b 运算符 a,并把 c 压入 S2,直到“(”出栈为止

(6)当表达式遍历完之后,从 S1 和 S2 弹出元素进行计算,结果数 = 次顶元素 运算符 栈顶元素,并将结果存入 S2,直到 S2 只有一个元素,该元素就是表达式的运算结果

 

前缀表达式(波兰表达式)

1、运算符位于操作符之前

2、求值步骤

(1)从右至左扫描表达式:遇数字,压入数栈;遇运算符,弹出数栈的栈顶、次顶元素,运算顺序:栈顶 运算符 次顶,运算结果入栈

(2)重复上述过程到表达式最左端,最后的运算值即结果

3、前缀表达式转换为中缀表达式

(1)从右至左扫描表达式

(2)如果是数字,则直接压栈

(3)如果是运算符 operator,则从栈顶先后弹出两个元素 a、b,然后将 (a operator b) 压栈

(4)将 (a operator b) 整体视作数字元素

(5)假设栈内有 c、(a operator1 b),此时扫描到 operator2,则依次弹出栈内两个元素 (a operator1 b)、c,然后将 ((a operator1 b) operator2 c)

(6)循环(1)-(3)扫描完表达式,返回栈顶元素,即为所需中缀表达式

 

后缀表达式(逆波兰表达式)

1、运算符位于操作符之后

2、求值步骤

(1)从左至右扫描表达式:遇数字,压入数栈;遇运算符,弹出数栈的栈顶、次顶元素,运算顺序:次顶 运算符 栈顶,运算结果入栈

(2)重复上述过程到表达式最右端,最后的运算值即结果

3、后缀表达式转换为中缀表达式

(1)从左至右扫描表达式

(2)如果是数字,则直接压栈

(3)如果是运算符 operator,则从栈顶先后弹出两个元素 a、b,然后将 (b operator a) 压栈

(4)将 (b operator a) 整体视作数字元素

(5)假设栈内有 c、(b operator1 a),此时扫描到 operator2,则依次弹出栈内两个元素 (b operator1 a)、c,然后将 (c operator 2 (a operator1 b))

(6)循环(1)-(3)扫描完表达式,返回栈顶元素,即为所需中缀表达式

 

直接转换法

例:a+b*c-(d+e)

1、中缀表达式转前缀表达式

(1)根据运算符的优先级对中缀表达式加括号:((a+(b*c))-(d+e))

(2)将运算符移到对应的括号前面:-(+(a*(bc))+(de))

(3)去掉所有括号,即为前缀表达式:-+a*bc+de

2、中缀表达式转后缀表达式

(1)根据运算符的优先级对中缀表达式加括号:((a+(b*c))-(d+e))

(2)将运算符移到对应的括号后面:((a(bc)*)+(de)+)-

(3)去掉所有括号,即为后缀表达式:abc*+de+-

 

中缀表达式转前缀表达式

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

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

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

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

(1)如果 S1 为空,或栈顶运算符为右括号“)”,则直接将此运算符入栈

(2)否则,若优先级 >= 栈顶运算符,也将运算符压入 S1

(3)否则,若优先级 < 栈顶运算符,将 S1 栈顶的运算符弹出并压入到 S2 中,再与 S1 中新的栈顶运算符相比较

5、遇到括号时

(1)如果是右括号“)”,则直接压入 S1

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

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

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

8、依次弹出 S2 中的元素并输出,结果即为中缓表达式对应的前缓表达式

 

中缀表达式转后缀表达式

1、初始化两个栈:运算符栈 s1 和储存中间结果的栈 s2

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

3、遇操作数,压入s2

4、遇运算符:

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

(2)若优先级 > 栈顶运算符,也将运算符压入 s1

(3)若优先级 <= 栈顶运算符,将 s1 栈顶的运算符弹出并压入到 s2 中,再与 s1 中新的栈顶运算符相比较

5、遇到括号时:

(1)若为左括号“(”,则直接压入 s1

(2)若为右括号“)”,则依次弹出 s1 栈顶的运算符,并压入 s2,直到遇到左括号“(”为止,此时将这一对括号丢弃

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

7、将 s1 中剩余运算符依次弹出并压入 s2

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

 

中缀转后缀计算实现

import java.util.LinkedList;
import java.util.List;

public class suffixExpressionCalculator {//后缀表达式计算器,不支持小数

    public static void main(String[] args) {
        String infix = "14 + 5 * 6 - ( 18 + 9 )";
        LinkedList<String> splitInfix = InfixToSuffix.split(infix);//分割中缀表达式,String转LinkedList
        LinkedList<String> suffix = InfixToSuffix.convert(splitInfix);//中缀表达式转后缀表达式
        for (String s : suffix) {
            System.out.print(s);
        }
        int result = calculate(suffix);
        System.out.println("后缀表达式运算结果:" + result);
    }

    public static int calculate(List<String> suffix) {//计算器
        LinkedList<String> linkedList = new LinkedList<>();
        for (String s : suffix) {
            if (s.matches("\\d+")) {//正则表达式,匹配多位数
                linkedList.addLast(s);
            } else {
                int num2 = Integer.parseInt(linkedList.removeLast());//栈顶元素
                int num1 = Integer.parseInt(linkedList.removeLast());//次顶元素
                int result;
                switch (s) {
                    case "+":
                        result = num1 + num2;
                        break;
                    case "-":
                        result = num1 - num2;
                        break;
                    case "*":
                        result = num1 * num2;
                        break;
                    case "/":
                        result = num1 / num2;
                        break;
                    default:
                        throw new RuntimeException("运算符有误\n");
                }
                linkedList.addLast("" + result);//栈内是String,将int转成String压入栈
            }
        }
        return Integer.parseInt(linkedList.removeLast());//栈内是String,将String转成int弹出栈
    }
}

class InfixToSuffix {

    public static LinkedList<String> split(String infix) {//传入中缀表达式,元素之间用空格隔开
        String[] temp = infix.split(" ");//首先将suffixExpression用空格进行分割
        LinkedList<String> splitInfix = new LinkedList<>();
        for (String s : temp) {
            splitInfix.addLast(s);
        }
        return splitInfix;
    }

    public static LinkedList<String> convert(LinkedList<String> splitInfix) {//中缀表达式转后缀表达式
        LinkedList<String> operator = new LinkedList<>();
        LinkedList<String> suffix = new LinkedList<>();
        for (String s : splitInfix) {
            if (s.matches("\\d+")) {//正则表达式,匹配多位数
                suffix.addLast(s);//压入suffix
            } else if (s.equals("(")) {//匹配左括号
                operator.addLast(s);//压入operator
            } else if (s.equals(")")) {//匹配右括号
                while (!("(".equals(operator.peekLast()))) {//若operator栈顶为左括号,退出循环
                    suffix.addLast(operator.pollLast());//operator栈顶元素弹出,压入suffix
                }
                operator.pollLast();//删除operator栈顶的左括号
            } else if (operator.peekLast() == null || "(".equals(operator.peekLast())) {//operator为空或 s 为左括号
                operator.addLast(s);//压入operator
            } else {//s 必为运算符
                //s 的优先级 <= operator栈顶运算符,或operator栈顶元素不是运算符,退出循环
                while ("+".equals(operator.peekLast()) || "-".equals(operator.peekLast())
                        || "*".equals(operator.peekLast()) || "/".equals(operator.peekLast())) {//
                    if (("+".equals(operator.peekLast()) || operator.peekLast().equals("-"))
                            && (s.equals("*") || s.equals("/"))) {//s 的优先级 > operator栈顶运算符
                        operator.addLast(s);//s 压入operator后,退出循环
                        break;
                    } else {//s 的优先级 <= operator栈顶运算符
                        suffix.addLast(operator.pollLast());//operator栈顶运算符压入suffix,继续循环
                    }
                }
                //当operator栈顶元素不是运算符,退出循环时,把 s 压入operator
                if (operator.peekLast() == null) {
                    operator.addLast(s);
                }
            }
        }
        while (operator.peekLast() != null) {//将operator中剩余运算符依次弹出并压入suffix
            suffix.addLast(operator.pollLast());
        }
        return suffix;
    }
}

 

posted @   半条咸鱼  阅读(286)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示