逆波兰表达式

该博客详细介绍了如何将中缀表达式转换为后缀表达式,包括步骤和具体实现的Java代码。通过中缀表达式如'(3+4)*5-6',首先将其转换为字符集合,然后使用栈数据结构进行中缀转后缀,最后实现逆波兰表达式计算器计算结果。整个过程涉及到了运算符优先级、括号处理等关键点。
摘要由CSDN通过智能技术生成
中缀转后缀

1)对表达式字符串中的数分别取出
2)对取出的字符做判断,符号存入,数字考虑拼接
3)再将取出的字符统一存储起来
4)初始化两个栈:运算符栈和储存中间结果的栈s2
5)从左至右扫描中缀表达式;
6)遇到操作数时,将其压入s2
7)遇到运算符时,比较其与s1栈顶运算符的优先级:
   1.如果s1为空或栈顶运算符为左括号“(”,则直接将此运算符入栈
   2.否则,若优先级比栈顶运算符高,也将运算符压入到s1
   3.否则,将s1栈顶的运算符弹出并压入到s2中,再次转到(7).1)与s1中新的栈顶运算符相比较﹔
8)遇到括号时:
   1.如果是左括号“(”,则直接压入s1
   2.如果是右括号“)”,则依次弹出s1栈顶的运算符,并压入s2,直到遇到左括号为止,此时将这一对括号丢弃
9)重复5-8,直至表达式中全部字符被操作
10)将s1中剩余的运算符依次弹出并压入s2
11)依次弹出s2中的元素并输出,结果的逆序即为中缀表达式对应的后缀表达式

public static List<String> toInfixExpression(String s){
        //创建一个集合来存放字符串分隔后的数据
        List<String> ls=new ArrayList<String>();
        //对字符串中字符取出时的索引
        int i=0;
        //用于拼接多位数
        String str;
        //定义字符承接从字符串中读取的字符
        char c;
        do {
            //数字0-9对应的ASCII码为48-57
            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;
    }
 //由中缀表达式的集合得到后缀表达式的集合
    public static List<String> toPostfixExpression(List<String> list){
        Stack<String> s1=new Stack<String>();
        List<String> l2=new ArrayList<String>();
        int i;

        for(String s:list){
            if(s.charAt(0)<48||s.charAt(0)>57){
                if (s1.empty()){
                    s1.push(s);
                }else if(isOper(s.charAt(0))){
                    while(true){
                        if (s1.isEmpty()){
                            s1.push(s);
                            break;
                        }else if (s1.peek().equals("(")){
                            s1.push(s);
                            break;
                        }else if (priority(s.charAt(0))>priority(s1.peek().charAt(0))){
                            s1.push(s);
                            break;
                        }else{
                            l2.add(s1.pop());
                            continue;
                        }
                    }
                }else if(s.equals("(")){
                    s1.push(s);
                }else if (s.equals(")")){
                    while (true){
                        if (s1.peek().equals("(")){
                            s1.pop();
                            break;
                        }else {
                            l2.add(s1.pop());
                        }
                    }
                }
            }else {
                l2.add(s);
            }
        }
        while (true){
            if (s1.isEmpty()){
               break;
            }
            l2.add(s1.pop());
        }
        return l2;
    }

由上述转化过程,我们可以进行以下实践
利用逆波兰表达式实现综合计算机

package Stack;

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

//逆波兰表达式计算(3+4)*5-6
public class PolandNotation {
    public static void main(String[] args) {
        Scanner scanner=new Scanner(System.in);
        List<String> l1=new ArrayList<String>();
        List<String> l2=new ArrayList<String>();
        //输入中缀表达式
        String infixExpression=scanner.next();
        //中缀表达式转中缀字符集合
        l1=toInfixExpression(infixExpression);
        l2=toPostfixExpression(l1);
        String postfixExpression=toPost(l2);
        //因为我们需要计算数值但逆波兰表达式被我们赋给了字符串类型,所以我们需要一个方法帮我们处理逆波兰的字符串
        List<String> rpnList=getListString(postfixExpression);

        //为了使主程序看起来更加简洁,这里定义一个计算方法将得到的集合放入计算得到结果
        int res=calculate(rpnList);
        System.out.println(infixExpression+"计算结果为"+res);
    }
    //后缀表达式各字符的集合和转后缀表达式
    public static String toPost(List<String> l2){
        String postExpression="";
        for (int i=0;i<l2.size();i++){
            if (i==l2.size()-1){
                postExpression+= l2.get(i);
                break;
            }
            postExpression+=l2.get(i);
            postExpression+=" ";
        }
        return postExpression;
    }
    //由中缀表达式的集合得到后缀表达式的集合
    public static List<String> toPostfixExpression(List<String> list){
        Stack<String> s1=new Stack<String>();
        List<String> l2=new ArrayList<String>();
        int i;

        for(String s:list){
            if(s.charAt(0)<48||s.charAt(0)>57){
                if (s1.empty()){
                    s1.push(s);
                }else if(isOper(s.charAt(0))){
                    while(true){
                        if (s1.isEmpty()){
                            s1.push(s);
                            break;
                        }else if (s1.peek().equals("(")){
                            s1.push(s);
                            break;
                        }else if (priority(s.charAt(0))>priority(s1.peek().charAt(0))){
                            s1.push(s);
                            break;
                        }else{
                            l2.add(s1.pop());
                            continue;
                        }
                    }
                }else if(s.equals("(")){
                    s1.push(s);
                }else if (s.equals(")")){
                    while (true){
                        if (s1.peek().equals("(")){
                            s1.pop();
                            break;
                        }else {
                            l2.add(s1.pop());
                        }
                    }
                }
            }else {
                l2.add(s);
            }
        }
        while (true){
            if (s1.isEmpty()){
               break;
            }
            l2.add(s1.pop());
        }
        return l2;
    }
    //定义一个方法处理中缀表达式,将其转化为一个集合
    public static List<String> toInfixExpression(String s){
        //创建一个集合来存放字符串分隔后的数据
        List<String> ls=new ArrayList<String>();
        //对字符串中字符取出时的索引
        int i=0;
        //用于拼接多位数
        String str;
        //定义字符承接从字符串中读取的字符
        char c;
        do {
            //数字0-9对应的ASCII码为48-57
            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;
    }

    //定义一个方法处理字符串
    public static List<String> getListString(String str){

        //split函数将字符串分隔成子字符串
        String[] split=str.split(" ");

        //将子字符串存入集合中便于后续操作
        List<String> list =new ArrayList<String>();
        for (String ele:split){
            list.add(ele);
        }
        //将集合返回
        return list;
    }

    //计算方法
    public static int calculate(List<String> list){
        //定义一个存放字符串的栈,用来存放数字字符
        Stack<String> stack=new Stack<String>();

        //通过遍历集合元素来实现计算
        //如果得到运算符号,则弹出栈中栈顶和次顶字符进行转型运算
        //如果得到数字字符(正则表达式判断),则存入栈中
        for (String da:list){
            if (da.matches("\\d+")){
                stack.push(da);
            }else {
                int num1=Integer.parseInt(stack.pop());
                int num2=Integer.parseInt(stack.pop());
                int res=0;
                if(da.equals("+")){
                    res=num1+num2;
                }else if (da.equals("-")){
                    res=num2-num1;
                }else if (da.equals("*")){
                    res=num1*num2;
                }else if (da.equals("/")){
                    res=num2/num1;
                }else {
                    throw new RuntimeException("运算符有误");
                }
                stack.push(res+"");
            }
        }
        return Integer.parseInt(stack.pop());
    }
    public static int priority(char oper){
        if (oper=='*'||oper=='/')
            return 1;
        else if (oper=='+'||oper=='-')
            return 0;
            //乘除计算优先级大于加减
        else return -1;//简单计算只包含+,-,*,/
    }
    //判断是否是运算符
    public static boolean isOper(char val){
        return val=='+'||val=='-'||val=='*'||val=='/';
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值