【问题标题】:Tree traversal in Java: Iterative or recursive? [closed]Java中的树遍历:迭代还是递归? [关闭]
【发布时间】:2014-08-21 08:51:48
【问题描述】:

今天和同事都写了一个java遍历树的方法。他以迭代的方式做到这一点,而我则递归。想象以下对象:

class TreeElement {
    private List<TreeElement> children;
    // Getters and setters...
}

以及两种可能的遍历方式:

方法一:

void traverseTree1(TreeElement rootElement) {
    List<TreeElement> q = new ArrayList<TreeElement>();
    q.add(rootElement);
    while(!q.isEmpty()) {
        TreeElement elem = q.get(0);
        handleElement(elem);
        q.addAll(elem.getChildren());
    }
}

方法二:

void traverseTree2(TreeElement element) {
    handleElement(element);
    for (TreeElement child : element.getChildren()) {
        traverseTree2(child);
    }
}

我现在的问题是,关于执行时间和内存使用情况,应该使用哪种方法?有什么真正的区别,还是编译器对代码进行了如此多的优化以至于没有?

PS:元素的遍历顺序并不重要。

【问题讨论】:

  • 方法二:调用自身。我认为这符合递归的条件。
  • 你确定这些方法是等价的吗?我认为第二个将按深度探索节点,而第一个按广度探索节点

标签: java recursion tree iteration


【解决方案1】:

在内存使用方面,traverseTree2 方法看起来更好,因为避免实例化 ArrayList 对象,考虑到创建对象总是需要一些时间,它也会对性能产生一些影响。我会使用 traverseTree2 方法。

【讨论】:

  • 第一种方法只实例化一个列表。这应该不是问题......
【解决方案2】:

我敢打赌,当涉及到执行时间时,这两种方法几乎是相等的。不过,您可以通过使用 Queue 而不是 List 来改进第一个。

但是,如果树很大,方法 2 会冒着获得StackOverflowError 的风险。方法 1 可以避免这种情况。

【讨论】:

  • 所以你的意思是第二种方法使用更多的内存。但是大约多少呢?这是一个明显的差异,比如内存的两倍甚至更多倍,还是更像是一个理论上的东西?
  • 不完全是。根据树的平衡方式,任何一个都可能占用更多内存。过多的递归会占用无法释放的局部变量和参数的内存,最终导致StackOverflowError
  • 而且你的栈(递归使用的)通常小于堆(ArrayList 使用的)。
【解决方案3】:

如果您担心方法性能,那么运行代码并对其进行分析可能符合您的最大利益。真的没有其他方法可以明确地告诉你哪种方法效果更好。

【讨论】:

  • 我知道这样一个抽象的问题没有确定的答案,但我希望从更有经验的程序员那里得到一些趋势和信息。
  • @ItsJustTony 在我看来(这只是一个猜测),我感觉递归方法会更快,因为它看起来整体调用的方法更少并且使用的条件更少。但同样,最好的确定方法是对其进行分析。
猜你喜欢
  • 2019-12-01
  • 2011-11-24
  • 2016-12-15
  • 2018-07-12
  • 2014-03-11
  • 1970-01-01
  • 2017-05-11
  • 2021-05-21
  • 2011-09-21
相关资源
最近更新 更多