数据结构与算法(12)——栈习题三

来源:互联网 发布:怎么电话联系淘宝卖家 编辑:程序博客网 时间:2024/06/16 10:05
题目: 一个对于一个单行的逆波兰表达式,由如下元素构成:数字:十进制数字字符构成的正整数,比如 223运算符:支持三种运算符^+和*,分别代表自增,加法和乘法分隔符:一个或者多个空格例如下面的字符串就是个逆波兰表达式2 3  4 * ^ 5 +逆波兰表达式在一个基于栈的虚拟机中求解,虚拟机的栈能保存16个整数,虚拟机从左向右扫描表达式,遇到整数就压栈,遇到表达式则从栈顶弹出若干个整数进行计算,计算结果重新压回栈中。其中运算符^从栈顶弹出一个整数,增加1之后压栈;运算符+和*从栈顶弹出两个整数,分别做相加和相乘运算后压栈。如果遇到运算符的时候,栈内没有足够的整数,称为下溢出,返回-1;把整数压栈的时候,如果栈没有足够的空间,称为上溢出,返回-2;如果整个计算过程中没有发生溢出,在整个表达式求解完成后,返回栈顶的整数。

说明:该题来自2017阿里巴巴实习笔试编程题,答案是自己写的,如有错误,敬请指正!

public class AlibabaTest {    public static void main(String[] args) {        ArrayList<Integer> inputs = new ArrayList<Integer>();        Scanner in = new Scanner(System.in);        String line = in.nextLine();        if(line != null && !line.isEmpty()) {            int res = resolve(line.trim());            System.out.println(String.valueOf(res));        }    }    // write your code here    public static int resolve(String expr) {        // 获取字符串集合        StringTokenizer st = new StringTokenizer(expr);        // 创建栈来存储操作数        LinkedListStack<Integer> stack = new LinkedListStack<Integer>();        // 遍历字符串集合        while (st.hasMoreTokens()) {            // 获取一个字符串            String str = st.nextToken();            switch (str) {            case "*":                // 双目操作需要保证数据栈至少有两个操作数                if (stack.size() >= 2) {                    int oper1 = stack.pop();                    int oper2 = stack.pop();                    stack.push(oper1 * oper2);                } else {                    // 栈内没有足够的整数,称为下溢出,返回-1                    return -1;                }                break;            case "+":                // 双目操作需要保证数据栈至少有两个操作数                if (stack.size() >= 2) {                    int oper1 = stack.pop();                    int oper2 = stack.pop();                    stack.push(oper1 + oper2);                } else {                    // 栈内没有足够的整数,称为下溢出,返回-1                    return -1;                }                break;            case "^":                if (!stack.isEmpty()) {                    int oper = stack.pop();                    oper += 1;                    stack.push(oper);                } else {                    // 栈内没有足够的整数,称为下溢出,返回-1                    return -1;                }                break;            default:                // 如果是操作数,直接入栈                stack.push(Integer.valueOf(str));                break;            }        }        // 返回栈顶元素        return stack.pop();    }}
题目:如何用栈只扫描一次就能计算中缀表达式的值?思路:1.创建一个空的操作数栈2.创建一个空的操作符栈3.遍历每一个字符,并根据情况处理  如果是数字则直接压入操作数栈  如果是操作符则判断优先级,并进行处理  如果是"("直接压入操作符栈  如果是")",则从操作符栈中弹出运算符,直到"("出栈;但"("不输出4.要保证操作数栈和操作符栈为空
/** * 计算中缀表达式结果 * @param infix 中缀表达式 * @return 运算结果 */public static int resultOfInfix(String infix) {    // 1.获取字符串集合    StringTokenizer st = new StringTokenizer(infix);    // 2.1 创建栈来存储操作数    LinkedListStack<Integer> datas = new LinkedListStack<Integer>();    // 2.2 创建栈来存储操作符    LinkedListStack<String> opers = new LinkedListStack<String>();    // 标记运算符优先级    boolean priority = false;    // 3.遍历字符串集合    while (st.hasMoreTokens()) {        // 3.1 获取下一个字符串        String str = st.nextToken();        boolean flag = false;        // 3.2 检查字符串        switch (str) {        case "(":        case "+":        case "-":        case "*":        case "/":            break;        // 遇到")"时,从栈中弹出运算符,直到"("出栈;但"("不输出        case ")":            while (!opers.top().equals("(")) {                calculate(datas, opers);            }            // 将"("弹出            opers.pop();            flag = true;            break;        default:            // 如果是操作数则压入数据栈            datas.push(Integer.valueOf(str));            flag = true;            break;        }        // 3.3 如果对")"和操作数做过处理,则结束当前循环,继续读取下一个字符串        if (flag) {            continue;        }        // 3.4 操作符栈不为空,则判断运算符优先级        if (!opers.isEmpty()) {            priority = compare(opers.top().toCharArray()[0], str.toCharArray()[0]);            // 栈内运算符优先级高            if (priority) {                calculate(datas, opers);            }        }        // 3.5 运算符入栈        opers.push(str);    }    // 4.操作符栈不为空,说明存在数据未处理    while (!opers.isEmpty()) {        calculate(datas, opers);    }    // 5.返回运算结果    return datas.pop();}/** * 运算 * @param datas 数据栈 * @param opers 操作符栈 */public static void calculate(LinkedListStack<Integer> datas, LinkedListStack<String> opers) {    int oper1 = datas.pop();    int oper2 = datas.pop();    switch (opers.pop()) {    case "*":        datas.push(oper2 * oper1);        break;    case "/":        datas.push(oper2 / oper1);        break;    case "+":        datas.push(oper2 + oper1);        break;    case "-":        datas.push(oper2 - oper1);        break;    default:        break;    }}

测试代码如下:

public static void main(String[] args) {    System.out.println("--------------------");    String string = "( 1 + 2 ) * ( 5 - 3 )";    int result = resultOfInfix(string);    // 结果为6    System.out.println(result);}
0 0
原创粉丝点击