Python 每日一记239>>>Java栈应用之求解逆波兰表达式

一、什么是逆波兰表达式

我们正常的计算表达式时这样的:(10*(9-5)+10)/2=25,这个叫中缀表达式,这样的话我们必须要判断优先级,当然对于我们来说判断优先级不是问题,但是对于计算机而言,却很麻烦。
那么如何不判断优先级呢,完全按从左到右进行计算,就是这样:
String[] expression={“10”,“9”,“5”,"-","",“10”,"+",“2”,"/"};主要思想就是,表达式前面的两个元素进行计算,然后结果整合为一个数,遇到表达式再计算,结果再放回去,从左到右,比如上面的表达式,先计算9-5=4,然后计算104=40,再计算40+10=50,最后50/2=25。

二、思路

  1. 循环遍历逆波兰表达式,如果不是运算符就装入栈
  2. 如果式运算符,就依次弹出两个元素pop1,pop2,运算pop2运算符pop1, 注意因为入栈时候pop2先入栈,pop1后入栈,因此要pop2运算符pop1,不能pop1运算符pop2
  3. 然后将运算的结果再入栈,继续上面的步骤
  4. 最后,循环完,取出栈中的元素就是最后的运算结果了

三、代码实现

/**
 * 求解逆波兰表达式
 * 先创建栈类
 * 然后创建计算方法
 * 最后测试
 * 
 * 特别注意
 * 因为入栈时候pop2先入栈,pop1后入栈,因此要pop2运算符pop1,不能式pop1运算符pop2
 */


package mypackage;

import java.util.Iterator;
//栈类
class Stack<T> implements Iterable<T> {

    //节点类
    private static class Node<T> {
        T data;
        Node next;

        //构造方法
        public Node(T data, Node next) {
            this.data = data;
            this.next = next;
        }
    }
    //    成员变量,头节点,节点个数
    Node head;
    int  N;
    //    构造方法
    public Stack(){
//        初始head不指向任何节点,元素个数为零
        this.head=new Node(null,null);
        this.N=0;
    }

    //    节点个数
    public int size(){
        return N;
    }

    //  是否为空
    public boolean isempty (){
        return N==0;
    }

    //    压栈,即向链表中添加元素,注意因为栈是先进后出,每次添加节点应该都是添加在首节点后,再让新节点指向之前的第一个节点
//    第一次添加元素是让首节点指向新节点,接着再添加节点,就要让首节点指向新节点,新节点指向之前的第一个节点,依次类推
    public void push(T data){
        if (N==0){
            Node newnode=new Node(data,null);
            head.next=newnode;
            N++;
        }
        else {
            Node oldfirst=head.next;
            Node newnode=new Node(data,null);
            head.next=newnode;
            newnode.next=oldfirst;
            N++;
        }
    }

    //    出栈
//    如果为空,则弹出null,
//    如果不为空,弹出head后的第一个元素,让head指向第二个元素
    public T pop() {
        Node oldfirst = head.next;
        if (oldfirst==null) {
            return null;
        }
        else {
            head.next = oldfirst.next;
            N--;
            return (T) oldfirst.data;
        }
    }

    //    重写,用于遍历
    @Override
    public Iterator<T> iterator() {
        // 返回的Iterator对象,创建一个内部类实现这个接口
        return new SIterator();
    }

    //    创建一个内部类实现Iterator接口
    public class SIterator implements Iterator {
        //        定义一个遍历的节点
        private Node n;
        public SIterator(){
//            初始化为0索引位置
            this.n=head;
        }
        //重写两个方法
        @Override
        public boolean hasNext() {
//            这个方法判断是否超出最大索引,如果超出会停止遍历
            return n.next!=null;
        }

        @Override
        public Object next() {
//            这个方法会遍历得每个节点
            n=n.next;
            return n.data;
        }
    }
}

//测试
public class MyJava {

//   逆波兰表达式求解方法
//   循环遍历逆波兰表达式,如果不是运算符就装入栈
//    如果式运算符,就依次弹出两个元素pop1,pop2,运算pop2运算符pop1
//    注意因为入栈时候pop2先入栈,pop1后入栈,因此要pop2运算符pop1,不能pop1运算符pop2
//    然后将运算的结果再入栈,继续上面的步骤
//    最后,循环完,取出栈中的元素就是最后的运算结果了
    private static int calculate(String[] expression) {
        Stack<Integer> stack=new Stack<>();
//        先定义变量
        Integer pop1;
        Integer pop2;
        Integer result;
//        开始循环
        for (int i=0;i<expression.length;i++){
            String exp=expression[i];
//            最好使用swith
            switch (exp){
//                如果是+
                case "+":
                    pop1=stack.pop();
                    pop2=stack.pop();
                    result=pop2+pop1;
                    stack.push(result);
                    break;
                case "-":
                    pop1=stack.pop();
                    pop2=stack.pop();
                    result=pop2-pop1;
                    stack.push(result);
                    break;
                case "*":
                    pop1=stack.pop();
                    pop2=stack.pop();
                    result=pop2*pop1;
                    stack.push(result);
                    break;
                case "/":
                    pop1=stack.pop();
                    pop2=stack.pop();
                    result=pop2/pop1;
                    stack.push(result);
                    break;
//                    如果不是运算符
                default:
//                    注意将String转化为Integar的方法Integer.parseInt
                    stack.push(Integer.parseInt(exp));

            }
        }
//        最后弹出的值就是结果
        return stack.pop();
    }

    public static void main(String[] args) {
//        逆波兰表达式(10*(9-5)+10)/2=25
        String[] expression={"10","9","5","-","*","10","+","2","/"};
        System.out.println("逆波兰表达式结果为:"+calculate(expression));
    }
}

结果:
在这里插入图片描述

发布了235 篇原创文章 · 获赞 24 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/weixin_44663675/article/details/105567305