【问题标题】:Recursion -- how to do an action only at the end递归——如何只在最后做一个动作
【发布时间】:2017-03-26 00:59:40
【问题描述】:

我有一个二叉搜索树,其中每个节点(GameEntry 类)代表一个“游戏玩法”(名称/分数对)。树是按名称(不是分数)组织的。我正在尝试为树编写一个方法来打印其前十名分数的列表(具有相应的名称)。我想过递归地遍历树,如果(且仅当)它是高分时,将一个节点放入一个数组(ScoreBoard 类)中。它有效,除了我的问题是记分牌会打印递归中的每一步。

public void printTopTen()
{
    ScoreBoard board = new ScoreBoard(10); // new scoreboard with capacity of 10
    printTopTenRecur(this.root, board);
}

// Auxillary method for printTopTen()
private void printTopTenRecur(GameEntry node, ScoreBoard board)
{
    if (node == null)
        {
            return;
        }
    printTopTenRecur(node.getLeft(), board);
    board.add(node); // adds the node to the scoreboard if it's a high score
    System.out.println(board);
    printTopTenRecur(node.getRight(), board);
}

我唯一能想到的就是在类上创建一个属性(称为board),然后在递归完成后打印出该属性。但是我收到了编译时错误void cannot be converted to String。我不知道还能怎么做。

public String printTopTen()
{
    ScoreBoard board = new ScoreBoard(10); // new scoreboard with capacity of 10
    printTopTenRecur(this.root, board);
    return System.out.println(this.board);
}

// Auxillary method for printTopTen()
private void printTopTenRecur(GameEntry node, ScoreBoard board)
{
    if (node == null)
        {
            return;
        }
    printTopTenRecur(node.getLeft(), board);
    board.add(node); // adds the node to the score board if it's a high score
    this.board = board; // assign local board to the board on the tree
    printTopTenRecur(node.getRight(), board);
}

【问题讨论】:

    标签: java recursion data-structures


    【解决方案1】:

    我不是很喜欢递归,尤其是java,主要原因是如果你走得太深,你会冒堆栈溢出的风险。其他语言处理这个问题,允许将尾调用隐式转换为 while 循环(例如 scala)。

    话虽如此,没有返回值的递归对我来说听起来很奇怪,而 moondaisy 的建议解决了您的问题,我宁愿返回分数而不是依赖于字段。

    private ScoreBoard printTopTenRecur(GameEntry node, ScoreBoard board){
      if(node == null )
        return board;
    
      board.add(node);
      ScoreBoard leftBoard = printTopTenRecur(node.getLeft(), board);
      ScoreBoard rightBoard = printTopTenRecur(node.getRight(), leftBoard);
    
      return rightBoard;
    }
    
    public void printTopTen(){
        ScoreBoard board = new ScoreBoard(10); // new scoreboard with capacity of 10
        // No need to return anything if you want to just print the result
        System.out.println(printTopTenRecur(this.root, board));
    }
    

    附注ScoreBoard leftBoard = printTopTenRecur(...) 那样毫无用处,董事会是可变的,所以通过它就足够了。

    当我认为递归时,我也认为不可变,所以我更希望ScoreBoard newBoard = board.update(node); 返回一个新的更新记分板,如下所示:

      ScoreBoard currentBoard = board.update(node);
      ScoreBoard leftBoard = printTopTenRecur(node.getLeft(), currentBoard);
      ScoreBoard rightBoard = printTopTenRecur(node.getRight(), leftBoard);
    

    这样printTopTenRecur是一个没有副作用的函数,所以是一个合适的函数。

    【讨论】:

    • 感谢您的不同观点,让我有很多思考。
    【解决方案2】:

    但是我得到了编译时错误 void cannot be convert to String

    您收到该错误是因为 System.out.println(this.board); 不是 String 并声明 printTopTen 应该返回 String

    如果您只想在递归结束时打印电路板,您可以这样做:

    public void printTopTen()
    {
        ScoreBoard board = new ScoreBoard(10); // new scoreboard with capacity of 10
        printTopTenRecur(this.root, board);
        System.out.println(this.board);
    }
    

    这将显示您在ScoreBoard 类的toString 方法中定义的任何内容。

    如果您想要返回String,您可以这样做:

    public String printTopTen()
    {
       ScoreBoard board = new ScoreBoard(10); // new scoreboard with capacity of 10
       printTopTenRecur(this.root, board);
       return this.board.toString();
    }
    

    【讨论】:

    • 谢谢您,您的建议有效。我现在意识到println 返回无效!在您更正后,我也尝试了return this.board.toString()。它编译,但我得到运行时错误 NoSuchMethodError。又糊涂了。
    猜你喜欢
    • 2011-10-16
    • 1970-01-01
    • 1970-01-01
    • 2011-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-03
    • 2021-12-25
    相关资源
    最近更新 更多