algs4|Dijkstra的双栈算术表达式求值算法Java

使用Java自身的输入输出库实现Dijkstra的双栈算术表达式求值算法

一、算法原理

计算表达式( 1 + ( ( 2 + 3 ) * ( 4 * 5 ) ) )

分析书上有,不赘述。算法如下:

将操作数压入操作数栈;
将运算符压入运算符栈;
忽略左括号;
在遇到右括号时,弹出一个运算符,弹出所需数量的操作数,并将运算符和操作数的运算结果压入操作数栈。

书上源码:

import java.util.Stack;

public class Evaluate {
    public static void main(String[] args) { 
        Stack<String> ops  = new Stack<String>();
        Stack<Double> vals = new Stack<Double>();

        while (!StdIn.isEmpty()) {
            String s = StdIn.readString();
            if      (s.equals("("))               ;
            else if (s.equals("+"))    ops.push(s);
            else if (s.equals("-"))    ops.push(s);
            else if (s.equals("*"))    ops.push(s);
            else if (s.equals("/"))    ops.push(s);
            else if (s.equals("sqrt")) ops.push(s);
            else if (s.equals(")")) {
                String op = ops.pop();
                double v = vals.pop();
                if      (op.equals("+"))    v = vals.pop() + v;
                else if (op.equals("-"))    v = vals.pop() - v;
                else if (op.equals("*"))    v = vals.pop() * v;
                else if (op.equals("/"))    v = vals.pop() / v;
                else if (op.equals("sqrt")) v = Math.sqrt(v);
                vals.push(v);
            }
            else vals.push(Double.parseDouble(s));
        }
        StdOut.println(vals.pop());
    }
}

二、问题

算法第四版中的Dijkstra的双栈算术表达式求值算法中,while (!StdIn.isEmpty()) 循环无法跳出

StdIn.isEmpty()的实现:

public static boolean isEmpty() {
    return !scanner.hasNext();
}

三、解决方法

法一|敌动我不动:

控制台输入以下快捷键:

macOSCommand+D

WindowsCtrl+D

原理:⌘D组合键可让您发送EOF(文件末尾),即表示无法从数据源读取更多数据。

法二|敌不动我动:

不用StdIn,使用Java自己的库重新写一遍

只处理了±*/,没有处理算术平方根

import java.util.Scanner;
import java.util.Stack;

public class MyEvaluate {
    public static void main(String[] args) {
        Stack<String> ops = new Stack<String>();
        Stack<Double> vals = new Stack<Double>();

        Scanner sc = new Scanner(System.in);
        String str;

        System.out.println("请输入算术表达式,中间用空格隔开,括号用英文字符:");
        str = sc.nextLine();
        String[] sArray = str.split(" ");
        for (String s : sArray) { // 迭代处理
            if (s.equals("(")) ; //不做处理
            //是否为操作符
            else if (s.equals("+") || s.equals("-") || s.equals("*") || s.equals("/")) ops.push(s);
            else if (s.equals(")")) { //右括号,取操作符和数字计算
                String op = ops.pop();
                double val = vals.pop();
                if (op.equals("+")) val = vals.pop() + val;
                else if (op.equals("-")) val = vals.pop() - val;
                else if (op.equals("*")) val = vals.pop() * val;
                else if (op.equals("/")) val = vals.pop() / val;
                vals.push(val);
            } else vals.push(Double.parseDouble(s));  //数,存入栈中
        }
        System.out.println(str + " = " + vals.pop());
    }
}

运算示例:
algs4DijkstraEx01

循环输入版本:

如果要循环计算算术表达式:

  1. 请在合适位置添加while(sc.hasNextLine())
  2. 除去提示语句,因为会造成输出上逻辑混乱,但是代码本身是可以执行的
  3. 设置退出条件,否则程序循环执行,就跟书上的一样了。
import java.util.Scanner;
import java.util.Stack;

public class MyEvaluate {
    public static void main(String[] args) {
        Stack<String> ops = new Stack<String>();
        Stack<Double> vals = new Stack<Double>();

        Scanner sc = new Scanner(System.in);
        String str;
        while (sc.hasNextLine()) {
            str = sc.nextLine();
            if (str.equals("q")) { //退出
                System.out.println("已退出,终止程序!");
                break;
            }
            String[] sArray = str.split(" ");
            for (String s : sArray) { // 迭代处理
                if (s.equals("(")) ; //不做处理
                    //是否为操作符
                else if (s.equals("+") || s.equals("-") || s.equals("*") || s.equals("/")) ops.push(s);
                else if (s.equals(")")) { //右括号,取操作符和数字计算
                    String op = ops.pop();
                    double val = vals.pop();
                    if (op.equals("+")) val = vals.pop() + val;
                    else if (op.equals("-")) val = vals.pop() - val;
                    else if (op.equals("*")) val = vals.pop() * val;
                    else if (op.equals("/")) val = vals.pop() / val;
                    vals.push(val);
                } else vals.push(Double.parseDouble(s));  //数,存入栈中
            }
            System.out.println(str + " = " + vals.pop());
        }
    }
}

示例:
algs4DijkstraEx02

附录

参考:

  1. Dijkstra的双栈算术表达式求值算法 Java实现 问题:char型,只能处理个位数
  2. java - 如何使StdIn.isEmpty()返回true?
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值