中缀表达式转后缀表达式并求值(实现多位操作数读取运算,包含具体Java代码)

3 篇文章 0 订阅

提出问题

上周数据结构实验课要求写一个中缀式转后缀式,并计算后缀式的值。成熟思路网上有很多,这里不再造轮子讲一遍了。

例如这篇:https://blog.csdn.net/Ring_k/article/details/79598961,这篇文章的举例部分,把中缀式转后缀式的过程一步步写了出来,显示了操作数读取、操作符栈、输出的状态,作者很细心,博主就是参考的这篇文章介绍的原理,感谢作者的原理讲解。

但是原文仅支持单个位数的操作数读取与运算,即操作数取值应为于‘0’-‘9’之间。如果操作数是67、88、45678这种多位操作数呢?

解决问题

原文中的中缀式转后缀式,该过程的本质是按字符读取每个操作数/操作符,一个字符塞入数组的一个单元格中,数组的一个单元格,当然只能容纳一个元素,即一个char占一个数组单元格。如每次读取一整个多位数呢?

博主想到了使用队列。使用Java泛型,把每个数组的单元格数据类型设置为一个队列。这样一个单元格就能存入多位操作数了,原则上,一个操作数/一个操作符/一个'('或')' 占用一个队列。

"6789"储存进了队列,'6', '7', '8', '9'依次进队

中缀表达式转后缀表达式具体运算时,原过程是依次读取数组中的每个单元格。现在,数组中每个单元格由一个char变为了一个队列,那么我们可以把队列中的多位操作数依次出队,这样,实现多位操作数的运算。

Java代码

本文代码参考了慕课网liuyubobobo老师的《Java语言玩转数据结构》中的“动态数组”,“动态数组实现栈”,“动态数组实现队列”,以这三个自定义的数据类型为基础,实现中缀表达式转后缀表达式算法原理。这三个自定义的数据类型的使用只是更加方便,原理还是一样的,java.util.Stack和java.util.Queue也可以做到。看不懂源码的可以参考本文前半部分的原理,自己动手实现学习效果更好哦。

附上博主关于bobo老师《Java语言玩转数据结构》的github学习代码仓库,持续更新中:https://github.com/JellyfishMIX/play_with_data_structures_java

工程目录结构:

InfixExpsToPostfixExps为中缀表达式转后缀表达式的实现过程

动态数组:

package com.algorithm.array;

public class Array<E> { //泛型
    private E[] data;
    private int size;

    // 构造函数,传入数组的容量capacity构造Array
    public Array(int capacity) {
        data = (E[]) new Object[capacity];  // java不支持new一个泛型类型的静态数组,需要中转一下。new一个Object类型的动态数组,然后强制转换成泛型类型
        size = 0;
    }

    // 无参的构造函数,默认数组的容量capacity=10
    public Array() {
        this(10);
    }

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

    // 获取数组的容量
    public int getCapacity() {
        return data.length;
    }

    // 判断数组是否为空
    public boolean isEmpty() {
        return size == 0;
    }

    // 向指定位置添加新元素
    public void add(int index, E e) {
        if (index < 0) {
            throw new IllegalArgumentException("getArrayElem failed. Require index>=0");
        }
        if (index > size) {
            throw new IllegalArgumentException("getArrayElem failed. Require index<=size");
        }

        // 若数组差1将满,则新建扩容数组,把原数组中数据逐个挪入新数组中,实现动态数组
        if (size == data.length-1) {
            resize(2 * data.length);
        }

        for (int i = size - 1; i >= index; i--) {
            data[i + 1] = data[i];
        }
        data[index] = e;
        size++;
    }

    // 向数组开头添加一个新元素
    public void addFirst(E e) {
        this.add(0, e);
    }

    // 向数组末尾添加一个新元素
    public void addLast(E e) {
        this.add(size, e);
    }

    // 删除指定位置的元素,返回删除的元素
    public E deleteByIndex(int index) {
        if (index < 0) {
            throw new IllegalArgumentException("getArrayElem failed. Require index>=0");
        }
        if (index > size) {
            throw new IllegalArgumentException("getArrayElem failed. Require index<=size");
        }

        E ret = data[index];
        for (int i = index; i < size; i++) {
            data[i] = data[i+1];
        }
        size--;
        data[size] = null;  // data[]中存放着一个个类对象的引用,data[size]还占用着一个引用,可以设为空,Java垃圾回收技术会释放掉占用的内存。非必须。该情况被称为loitering objects,注意: loitering objects != memory leak

        if (size == data.length/4 && data.length/2 != 0) {
            this.resize(data.length/2);
        }
        return ret;
    }

    // 删除数组开头元素
    public E deleteFirst() {
        E ret = deleteByIndex(0); //E ret 是作为接收deleteByIndex()的返回值
        return ret;
    }

    // 删除数组末尾元素
    public E deleteLast() {
        E ret = deleteByIndex(size-1); //E ret 是作为接收deleteByIndex()的返回值
        return ret;
    }

    // 删除指定的某个元素
    public void delete(E e) {
        int index = find(e);
        if (index != -1) {
            E ret = deleteByIndex(index); //E ret 是作为接收deleteByIndex()的返回值,无实际作用
        }
    }

    // 获得index索引位置元素
    public E get(int index) {
        if (index < 0) {
            throw new IllegalArgumentException("getArrayElem failed. Require index>=0");
        }
        if (index >= size) {
            throw new IllegalArgumentException("getArrayElem failed. Require index<size");
        }

        return data[index];
    }

    // 获得第一个元素
    public E getFirst() {
        return get(0);
    }

    // 获得最后一个元素
    public E getLast() {
        return get(size-1);
    }

    // 设置index索引位置元素
    public void set(int index, E e) {
        if (index < 0 || index >= size) {
            throw new IllegalArgumentException("setArrayElem failed. Require index>=0 && index<=size");
        }
        data[index] = e;
    }

    // 查找数组中是否有元素e
    public boolean isContain(E e) {
        for (int i = 0; i < size; i++) {
            if (data[i].equals(e)) { // data[i]和e都是类对象,equals()是值比较,比较两个对象的值是否相等。 ==是引用比较,比较变量名区域所放的值是否相等。
                return true;
            }
        }
        return false;
    }

    // 查询数组中元素e所在的索引,如果不存在元素e,则返回-1
    public int find(E e) {
        for (int i = 0; i < size; i++) {
            if (data[i].equals(e)) { // data[i]和e都是类对象,equals()是值比较,比较两个对象的值是否相等。 ==是引用比较,比较变量名区域所放的值是否相等。
                return i;
            }
        }
        return -1;
    }

    // 新建扩容数组,把原数组中数据逐个挪入新数组中,实现动态数组
    private void resize(int newCapacity) {
        E[] newData = (E[]) new Object[newCapacity];
        for (int i=0; i<size; i++) {
            newData[i] = data[i];
        }
        data = newData;
    }

    @Override
    public String toString() {
        StringBuilder res = new StringBuilder();
        res.append(String.format("Array: size=%d, capacity=%d\n", size, data.length));
        res.append('[');
        for (int i = 0; i < size; i++) {
            res.append(data[i]);
            if (i != size - 1) {
                res.append(", ");
            }
        }
        res.append(']');
        return res.toString();
    }
}

 

动态数组实现栈(可以使用java.util.Stack代替):

接口:

package com.algorithm.stack;

public interface Stack<E> {
    int getSize();
    boolean isEmpty();
    void push(E e); // 入栈
    E pop();    // 出栈
    E peek();   // 获取栈顶元素
}

实现接口:

package com.algorithm.stack.arraystack;

import com.algorithm.array.Array;
import com.algorithm.stack.Stack;

public class ArrayStack<E> implements Stack<E> {
    Array<E> array; // 动态数组Array,capacity任意

    public ArrayStack() {
        array = new Array<>();
    }
    public ArrayStack(int capacity) {
        array = new Array<>(capacity);
    }

    @Override
    public int getSize() {
        return array.getSize();
    }

    @Override
    public boolean isEmpty() {
        return array.isEmpty();
    }

    // getCapacity()是动态数组Array实现Stack所特有的,Stack本身没有该方法。因为只有动态数组才有capacity这一概念
    public int getCapacity() {
        return array.getCapacity();
    }

    @Override
    // 入栈
    public void push(E e) {
        array.addLast(e);
    }

    @Override
    // 出栈
    public E pop() {
        return array.deleteLast();
    }

    @Override
    // 获取栈顶元素
    public E peek() {
        return array.getLast(); // 判断栈是否为空的逻辑在Array中
    }

    @Override
    public String toString() {
        StringBuilder res = new StringBuilder();
        res.append("Stack: ");
        res.append("[");
        for(int i = 0; i<array.getSize(); i++) {
            res.append(array.get(i));
            if (i != array.getSize()-1)
                res.append(", ");
        }
        res.append("] top");
        return res.toString();
    }
}

 

动态数组实现队列(可以使用java.util.Queue代替):

接口:

package com.algorithm.queue;

public interface Queue<E> {
    int getSize();
    boolean isEmpty();
    void enqueue(E e);  // 入队
    E dequeue();    // 出队
    E getFront();   // 获取队首元素
}

实现接口:

package com.algorithm.queue.arrayqueue;

import com.algorithm.array.Array;
import com.algorithm.queue.Queue;

public class ArrayQueue<E> implements Queue<E> {
    private Array<E> array;

    // 构造方法
    public ArrayQueue() {
        array = new Array<>();
    }
    public ArrayQueue(int capacity) {
        array = new Array<>(capacity);
    }

    @Override
    public int getSize() {
        return array.getSize();
    }

    @Override
    public boolean isEmpty() {
        return array.isEmpty();
    }

    @Override
    // 入队
    public void enqueue(E e) {
        array.addLast(e);
    }

    @Override
    // 出队
    public E dequeue() {
        return array.deleteFirst();
    }

    @Override
    // 获取队首元素
    public E getFront() {
        return array.get(0);    // 判断栈是否为空的逻辑在Array中
    }

    @Override
    public String toString() {
        StringBuilder res = new StringBuilder();

        res.append("Queue: ");
        res.append("front [");
        for (int i=0; i<array.getSize(); i++) {
            res.append(array.get(i));
            if (i != array.getSize()-1) {
                res.append(", ");
            }
        }
        res.append("] tail");

        return res.toString();
    }
}

中缀表达式转后缀表达式

源码:

package com.algorithm.stack.problems.infixexpstopostfixexps;

import com.algorithm.array.Array;
import com.algorithm.queue.arrayqueue.ArrayQueue;
import com.algorithm.stack.arraystack.ArrayStack;

// convert infix expression to a postfix expression
public class InfixExpsToPostfixExps {
    Array<ArrayQueue<Character>> infixArray = new Array<>();    // 中缀式字符串队列集合,infixArray每个元素都是一个队列。原则上 一个操作数/一个操作符/一个'('或')' 占用一个队列

    // 中缀式字符串使用队列储存,以处理多位操作数。原则上 一个操作数/一个操作符/一个'('或')' 占用一个队列
    public void inputStr(String str) {
        int count = 0;  // 记录第几个infixArray元素将要存储,即第几个队列将要进行存储
        infixArray.addLast(new ArrayQueue());
        boolean isContinuousOperator = false;   // 锁,防止多个操作符连续出现导致infixArray中有空元素出现
        for (int i=0; i<str.length(); i++) {
            char c = str.charAt(i);
            if (c == '+' || c == '-' || c == '*' || c == '/' || c == '(' || c == ')') {
                if (isContinuousOperator != true) {
                    count++;
                    infixArray.addLast(new ArrayQueue());
                }
                infixArray.get(count).enqueue(c);
                count++;
                infixArray.addLast(new ArrayQueue());
                isContinuousOperator = true;    // 加入了操作符,加锁
                continue;
            }
            infixArray.get(count).enqueue(c);
            isContinuousOperator = false;   // 加入了操作数,解锁
        }
        // 输入是操作符后,操作符本身占了一个infixArray元素,此外infixArray中必定还会多加一个元素。防止因为最后一次输入是操作符,导致infixArray中最后一个元素为空
        if (isContinuousOperator == true) {
            infixArray.deleteLast();
        }
    }

    // 显示中缀式字符串队列集合infixArray中储存的元素
    public void outputInfixArray() {
        System.out.println(infixArray);
    }

    // 测试"中缀式字符串使用队列储存"的效果
    public void testOutputInfixArray() {
        InfixExpsToPostfixExps infixExpsToPostfixExps = new InfixExpsToPostfixExps();
        infixExpsToPostfixExps.inputStr("6789+2*(679*(3-1*345+1))");
        infixExpsToPostfixExps.outputInfixArray();
    }

    StringBuilder postfixExpsBuilder = new StringBuilder();    // 后缀表达式字符串构建器
    ArrayStack<Character> postfixArrayStack = new ArrayStack<>();   // 储存操作符的栈
    Array<ArrayQueue<Character>> postfixArray = new Array<>();    // 可以理解为postfixExpsBuilder的记录器。postfixArray每个元素都是一个队列。原则上 一个操作数/一个操作符/一个'('或')' 占用一个队列。后缀式字符串使用队列储存,以处理多位操作数。原则上 一个操作数/一个操作符/一个'('或')' 占用一个队列

    /**
     * 中缀转化为后缀表达式
     * 1.按次序读取中缀表达式的字符。
     * 2.读到一个操作数的时候,立即放入到输出中。
     * 3.从栈顶到第一个优先级不大于(小于,低于或等于)它的运算符(或 '(',但优先满足前一个条件)之间的运算符加入后缀表达式中,该运算符再入栈
     *   通俗理解:设预设操作符为'+', '-', '*', '/'。
     *   设读取为'*',开始检测操作符栈顶是「同级或更高运算级符号」or「比自己低级的运算级符号」
     *      如果遇到「同级或更高运算级符号」,例如'*'或'/',则将此「同级或更高运算级符号」赶出栈
     *      如果遇到「同级或更高运算级符号」,例如'*'或'/',则将此「同级或更高运算级符号」赶出栈
     *      如果遇到「同级或更高运算级符号」,例如'*'或'/',则将此「同级或更高运算级符号」赶出栈...
     *          每次赶出操作符后检测是否操作符栈为空,为空栈则将自己压入栈,停止检测
     *          每次检测中,如果遇到了'(',则将'('保留,自己进栈
     *      如果遇到「比自己低级的运算级符号」,例如'+'或'-',则将此「比自己低级的运算级符号」保留,自己入栈,停止检测
     *   设读取为'+',开始检测操作符栈顶是「同级或更高运算级符号」or「比自己低级的运算级符号」
     *      如果遇到「同级或更高运算级符号」,例如'+'或'-',则将此「同级或更高运算级符号」赶出栈
     *      如果遇到「同级或更高运算级符号」,例如'+'或'-',则将此「同级或更高运算级符号」赶出栈
     *      如果遇到「同级或更高运算级符号」,例如'+'或'-',则将此「同级或更高运算级符号」赶出栈...
     *          每次赶出操作符后检测是否操作符栈为空,为空栈则将自己压入栈,停止检测
     *          此处,由于预设操作符中运算级别最低的是'+', '-',没有比其更低的,所以'+', '-'会一直将栈中的操作符赶出去,直到遇到'('或空栈
     *              如果遇到了'(',则将'('保留,自己进栈
     *              如果遇到了空栈,则自己进栈
     *      如果遇到「比自己低级的运算级符号」,例如'=='或'!=',则将此「比自己低级的运算级符号」保留,自己入栈,停止检测
     *  4.读到操作符“)”,则从栈中弹出栈元素并输出,直到遇到第一个“(”为止。其中“(”不再添加到输出中,而是直接舍弃。
     *  5.当输入为空时,把栈里的操作符全部依次弹出并输出。
     */
    public void toPostfixExps() {
        int count = 0;  // 记录第几个postfixArray元素将要存储,即第几个队列将要进行存储
        postfixArray.addLast(new ArrayQueue());
        for (int i=0; i<infixArray.getSize(); i++) {
            char frontElem = infixArray.get(i).getFront();  // 获取infixArray中的当前队列队首,用来做读取判断。除用作判断外,别无他用
            if (frontElem != '+' && frontElem != '-' && frontElem != '*' && frontElem != '/' && frontElem != '(' && frontElem != ')') {
                int myQueueSize = infixArray.get(i).getSize();  // 接下来的for循环过程中,infixArray.get(i).getSize()的值会改变,因此先记录下来
                for (int j=0; j<myQueueSize; j++) {
                    postfixArray.get(count).enqueue(infixArray.get(i).getFront());  // 记录后缀表达式,后缀式字符串使用队列储存,以处理多位操作数。原则上 一个操作数/一个操作符/一个'('或')' 占用一个队列
                    postfixExpsBuilder.append(infixArray.get(i).getFront()); // 输出后缀表达式到字符串到StringBuilder
                    infixArray.get(i).dequeue();    // infixArray中的当前队列出队
                }

                count++;
                postfixArray.addLast(new ArrayQueue());
            } else if (frontElem == '(') {
                postfixArrayStack.push(infixArray.get(i).getFront());   // 获取infixArray中的当前队列队首(其实当前队列中只有一个操作符'(')
                infixArray.get(i).dequeue();    // infixArray中的当前队列出队
            } else if (frontElem == ')') {
                infixArray.get(i).dequeue();    // 进入到')'分支,当前'('使命就此终结。infixArray中的当前队列出队,即'('出队
                while (postfixArrayStack.peek() != '(') {
                    postfixArray.get(count).enqueue(postfixArrayStack.peek());  // 记录后缀表达式,后缀式字符串使用队列储存,以处理多位操作数。原则上 一个操作数/一个操作符/一个'('或')' 占用一个队列
                    postfixExpsBuilder.append(postfixArrayStack.peek()); // 输出后缀表达式到字符串到StringBuilder
                    postfixArrayStack.pop();

                    count++;
                    postfixArray.addLast(new ArrayQueue());
                }
                postfixArrayStack.pop();    // 发现postfixArrayStack中的'(',将其出栈
            } else if (frontElem == '*' || frontElem == '/') {
                // 读到操作符“+”,“-”,“*”,“/”,则从栈中弹出栈元素并输出,直到遇到优先级更低或者“(”的为止操作符为止。读取到的该运算符再入栈

                // 判断栈是否为空,若为空,则直接把'*'或'/'压入栈中。没有此步判空会导致后面的postfixArrayStack.peek()报异常
                if (postfixArrayStack.isEmpty()) {
                    postfixArrayStack.push(infixArray.get(i).getFront());
                    infixArray.get(i).dequeue();    // infixArray中的当前队列出队
                    continue;
                }
                while (postfixArrayStack.peek() != '+' && postfixArrayStack.peek() != '-' && postfixArrayStack.peek() != '(') {
                    postfixArray.get(count).enqueue(postfixArrayStack.peek());  // 记录后缀表达式,后缀式字符串使用队列储存,以处理多位操作数。原则上 一个操作数/一个操作符/一个'('或')' 占用一个队列
                    postfixExpsBuilder.append(postfixArrayStack.peek()); // 输出后缀表达式到字符串到StringBuilder
                    postfixArrayStack.pop();    // 栈顶元素出栈

                    count++;
                    postfixArray.addLast(new ArrayQueue());

                    // 检测逻辑会不断取栈顶检测,但如果栈中没有( 或 '+' 或'-',会取空栈的栈顶,显然空栈是没有栈顶的,会报异常。因此每次从栈中赶出一个操作符,都要检测一下是否为空栈
                    if (postfixArrayStack.isEmpty()) {
                        break;
                    }
                }

                postfixArrayStack.push(infixArray.get(i).getFront());
                infixArray.get(i).dequeue();    // infixArray中的当前队列出队
            } else if (frontElem == '+' || frontElem == '-') {
                // 读到操作符“+”,“-”,“*”,“/”,则从栈中弹出栈元素并输出,直到遇到优先级更低或者“(”的为止操作符为止。读取到的该运算符再入栈
                // 通俗解释:如果出现'+'或'-',一直把栈中操作符赶出去,直到遇到'('为止,不会把'('赶出去

                // 判断栈是否为空,若为空,则直接把'+'或'-'压入栈中。没有此步判空会导致后面的postfixArrayStack.peek()报异常
                if (postfixArrayStack.isEmpty()) {
                    postfixArrayStack.push(infixArray.get(i).getFront());
                    infixArray.get(i).dequeue();    // infixArray中的当前队列出队
                    continue;
                }
                while (postfixArrayStack.peek() != '(') {
                    postfixArray.get(count).enqueue(postfixArrayStack.peek());  // 记录后缀表达式,后缀式字符串使用队列储存,以处理多位操作数。原则上 一个操作数/一个操作符/一个'('或')' 占用一个队列
                    postfixExpsBuilder.append(postfixArrayStack.peek()); // 输出后缀表达式到字符串到StringBuilder
                    postfixArrayStack.pop();    // 栈顶元素出栈

                    count++;
                    postfixArray.addLast(new ArrayQueue());

                    // 如果读取为'+'或'-',一直把栈中操作符赶出去,直到遇到'('为止,不会把'('赶出去
                    // 上述逻辑会不断取栈顶检测,但如果栈中没有(,会取空栈的栈顶,显然空栈是没有栈顶的,会报异常。因此每次从栈中赶出一个操作符,都要检测一下是否为空栈
                    if (postfixArrayStack.isEmpty()) {
                        break;
                    }
                }
                postfixArrayStack.push(infixArray.get(i).getFront());
                infixArray.get(i).dequeue();    // infixArray中的当前队列出队
            }
        }

        // 当结束读取时,把栈里的操作符全部依次弹出并输出
        while (!postfixArrayStack.isEmpty()) {
            postfixArray.get(count).enqueue(postfixArrayStack.peek());  // 记录后缀表达式,后缀式字符串使用队列储存,以处理多位操作数。原则上 一个操作数/一个操作符/一个'('或')' 占用一个队列
            postfixExpsBuilder.append(postfixArrayStack.peek()); // 输出后缀表达式到字符串到StringBuilder
            postfixArrayStack.pop();    // 栈顶元素出栈

            count++;
            postfixArray.addLast(new ArrayQueue());
        }
    }

    // 打印中缀式字符串存储队列集合,打印后缀表达式postfixExps, 后缀表达式记录器postfixArray, 后缀栈postfixArrayStack
    public void printPostfixExps() {
        String postfixExps = postfixExpsBuilder.toString();
        System.out.println("后缀表达式为:");
        System.out.println(postfixExps);
        // System.out.println("中缀式字符串存储队列集合为:");
        // System.out.println(infixArray); // 打印中缀式字符串存储队列集合,查看是否全部出队
        System.out.println("后缀表达式的存储队列集合为:");
        System.out.println(postfixArray);   // 打印后缀表达式的存储队列集合postfixArray
        // System.out.println(postfixArrayStack);
    }

    ArrayStack<Double> operandStack = new ArrayStack<>();  // 操作数栈
    /**
     * 后缀表达式求值
     * 1.按次序读取后缀表达式的每一个字符。
     * 2.读取到操作数时,把操作数压入栈中。
     * 3.读取到操作符时,对栈顶的2个操作数做相应运算,要注意操作数的前后顺序。结果压入栈中。
     * 4.读取完所有的字符后,弹出栈。得到的值就是所求结果。
     * @return
     */
    public double calcPostfixExps() {
        for (int i=0; i<postfixArray.getSize()-1; i++) {
            char frontElem = postfixArray.get(i).getFront();    // 获取postfixArray中的当前队列队首,用来做读取判断。除用作判断外,别无他用
            if (frontElem != '+' && frontElem != '-' && frontElem != '*' && frontElem != '/') {
                int myQueueSize = postfixArray.get(i).getSize();  // 接下来的for循环过程中,infixArray.get(i).getSize()的值会改变,因此先记录下来
                double myNumber = 0;   // 记录当前多位操作数数值
                for (int j=0; j<myQueueSize; j++) {
                    int myOperand = postfixArray.get(i).dequeue() - '0';
                    myNumber += myOperand * Math.pow(10, ((double)myQueueSize-j-1));
                }

                operandStack.push(myNumber);    // 操作数入栈
                // System.out.println(operandStack);   // 打印操作数栈,展示后缀表达式运算过程第一处。第一处在207行 ,第二处在226行,第三处在230行
            } else {
                double a = operandStack.pop();
                char operator = postfixArray.get(i).getFront(); // 获取操作符
                postfixArray.get(i).dequeue();  // 操作符出队列,给下个操作符腾空间
                double b = operandStack.pop();

                double myRes = 0;
                if (operator == '+') {
                    myRes = b + a;
                } else if (operator == '-') {
                    myRes = b - a;
                } else if (operator == '*') {
                    myRes = b * a;
                } else if (operator == '/'){
                    myRes = b / a;
                }

                operandStack.push(myRes);
                // System.out.println(operandStack);   // 打印操作数栈,展示后缀表达式运算过程第二处。第一处在207行 ,第二处在226行,第三处在230行
            }
        }

        // System.out.println(operandStack);   // 打印操作数栈,展示后缀表达式运算过程第三处。第一处在207行 ,第二处在226行,第三处在230行
        return operandStack.pop();
    }
}

测试运行效果:

package com.algorithm.stack.problems.infixexpstopostfixexps;

import java.util.Scanner;

public class Test {
    public static void main(String[] args) {
        InfixExpsToPostfixExps infixExpsToPostfixExps = new InfixExpsToPostfixExps();
        Scanner input = new Scanner(System.in);

        // // 测试"中缀式字符串使用队列储存"的效果
        // infixExpsToPostfixExps.testOutputInfixArray();

        // // 预设输入测试区
        // // infixExpsToPostfixExps.inputStr("6789+2*(3*(3-1*2+1))");
        // // infixExpsToPostfixExps.inputStr("5+2*(3*(3-1*2+1))");
        // infixExpsToPostfixExps.inputStr("670+9*3");

        // 手动输入区
        System.out.print("请输入一行中缀式运算符(操作数位数任意,可选操作符为'+', '-', '*', '/'):");
        String inputStr = input.nextLine();
        infixExpsToPostfixExps.inputStr(inputStr);

        // 执行区
        // System.out.println("中缀表达式字符串存储集合为");
        // infixExpsToPostfixExps.outputInfixArray();  // 打印中缀式字符串存储队列集合
        infixExpsToPostfixExps.toPostfixExps(); // 转化为后缀表达式
        System.out.println("----------------------------");
        infixExpsToPostfixExps.printPostfixExps(); // 打印后缀表达式postfixExps, 后缀表达式记录器postfixArray, 后缀栈postfixArrayStack,可选择打印。
        System.out.println("----------------------------");
        double res = infixExpsToPostfixExps.calcPostfixExps();  // 计算后缀表达式
        System.out.println("后缀表达式运算结果为:" + res);
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JellyfishMIX

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值