利用栈实现逆波兰表达式(后缀表达式)问题求解

逆波兰表达式(后缀表达式)问题
波兰表达式又叫做后缀表达式。逆波兰表示法是波兰逻辑学家J・卢卡西维兹(J・ Lukasewicz)于1929年首先提出的一种表达式的表示方法 [1] 。后来,人们就把用这种表示法写出的表达式称作“逆波兰表达式”。逆波兰表达式把运算量写在前面,把算符写在后面。
在这里插入图片描述解决思路:

  1. 定义一个栈,用来存储操作数;
  2. 从左到右遍历逆波兰表达式,得到每一个元素;
  3. 判断当前元素是运算符还是操作数;
  4. 如果是运算符,从栈中弹出两个操作数,完成运算,运算玩的结果再压入栈中;
  5. 操作数,把该操作数放入到栈中;
  6. 栈中最后一个元素,就是逆波兰表达式的结果,即是运算后的结果;
    在这里插入图片描述实现代码如下:
public class ReversePolishNotationTest {
    public static void main(String[] args) {
        //中缀表达式:3*(17-15)+18/6的逆波兰表达式如下
        String[] notation = {"3","17","15","-","*","18","6","/","+"};
        int result = caculate(notation);
        System.out.println("逆波兰表达式的结果为:"+result);
    }

    /**
     * @param notation 逆波兰表达式的数组表示方式
     * @return  逆波兰表达式的计算结果
     */
    public static int caculate(String[] notation){
        //1.定义一个栈,用来存储操作数
        Stack<Integer> oprands = new Stack<Integer>();
        //2.从左到右遍历逆波兰表达式,得到每一个元素
        for (int i = 0; i < notation.length; i++) {
            String curr = notation[i];
            //3.判断当前元素是运算符还是操作数
            Integer o1;
            Integer o2;
            Integer result;
            switch (curr){
                case "+":{
                    //4.运算符,从栈中弹出两个操作数,完成运算,运算玩的结果再压入栈中
                    o1 = oprands.pop();
                    o2 = oprands.pop();
                    result = o2 + o1;
                    oprands.push(result);
                    break;
                }
                case "-":{
                    //4.运算符,从栈中弹出两个操作数,完成运算,运算玩的结果再压入栈中
                    o1 = oprands.pop();
                    o2 = oprands.pop();
                    result = o2 - o1;  //注意:这个必须为o2-o1:由栈的性质可以后进先出,所以本程序中o1 == 15,o2 == 17;
                    oprands.push(result);
                    break;
                }
                case "*":{
                    //4.运算符,从栈中弹出两个操作数,完成运算,运算玩的结果再压入栈中
                    o1 = oprands.pop();
                    o2 = oprands.pop();
                    result = o2 * o1;
                    oprands.push(result);
                    break;
                }
                case "/":{
                    //4.运算符,从栈中弹出两个操作数,完成运算,运算玩的结果再压入栈中
                    o1 = oprands.pop();
                    o2 = oprands.pop();
                    result = o2 / o1;  //注意:这个必须为o2/o1:由栈的性质可以后进先出,所以本程序中o1 == 6,o2 == 18;
                    oprands.push(result);
                    break;
                }
                default:
                    //5.操作数,把该操作数放入到栈中
                    oprands.push(Integer.parseInt(curr));
                    break;
            }
        }
        //6.得到栈中最后一个元素,就是逆波兰表达式的结果
        int result = oprands.pop();
        return result;
    }
}


//栈的设计
public class Stack<T>  {
    //记录首结点
    private Node  head;
    //栈中元素的个数
    private int N;

    private class Node{
        //存储数据
        public T item;
        //指向下一个结点
        public Node next;

        public Node(T item,Node next){
            this.item = item;
            this.next = next;
        }
    }

    public Stack(){
        this.head = new Node(null,null);
        this.N = 0;
    }

    //判断当前栈中元素个数是否为0
    public boolean isEmpty(){
        return N == 0;
    }

    //获取栈中元素的个数
    public int size(){
        return N;
    }

    //把t元素压入栈
    public void push(T t){
       //找到首结点指向的第一个结点
        Node oldNode = head.next;
        //创建新节点
        Node newNode = new Node(t, null);
        //让首结点指向新节点
        head.next = newNode;
        //让新结点指向原来的第一个结点
        newNode.next = oldNode;
        //元素个数+1
        N++;
    }

    //弹出栈顶元素
    public T pop(){
       //找到首结点指向的第一个结点
        Node oldFirst = head.next;
        //让首结点指向原来第一个结点的下一个结点
        if(oldFirst == null){
            return null;
        }
        head.next = oldFirst.next;
        //元素个数-1
        N--;

        return oldFirst.item;
    }
}

程序运行的结果:
在这里插入图片描述有运行结果可以程序运行成功!

发布了22 篇原创文章 · 获赞 21 · 访问量 1384

猜你喜欢

转载自blog.csdn.net/qq_43751200/article/details/104619611