递归或循环

时间:2012-11-12 15:23:06

标签: java loops recursion

我有这个计算一些统计数据的方法:

public void calculateAverage(int hour){

    if (hour != 20) {
        int data =0; 
        int times = 0;
        for (CallQueue cq : queues) {
            data += cq.getCallsByTime().get(hour);
            times++;
        }       
        averageData.add((double)data/times);
        calculateAverage(hour + 1);
    }

}

现在我很自豪我创建了一个递归方法,但我知道这可以通过循环解决。

我的问题是:以递归或循环方式解决这类问题会更​​好吗?

如果你有时间解释你的答案,请()

5 个答案:

答案 0 :(得分:6)

一般的递归

通常,递归会更昂贵,因为每次函数递归时都必须使用变量副本修改堆栈。

一组地址&需要保存状态,以便递归过程可以在特定运行后返回到正确的状态

如果可能,迭代会更好。递归,当迭代不会削减它,或者会导致更复杂的代码


代码维护

从维护的角度来看,调试迭代代码比递归过程容易得多,因为与思考特定递归相比,相对容易了解状态在任何特定迭代中的状态。


您的代码

该过程调用自身,但每次运行都与上一次运行的结果无关。 每次运行都是独立的,通常是最大的赠品,的递归可能没有必要

在我看来,calculateAverage(hour + 1);应该移到函数之外,因为读取代码的人也会更清楚。每个电话都是独立的。

答案 1 :(得分:2)

在Java,C和Python中,与迭代(通常)相比,递归相当昂贵,因为它需要分配新的堆栈帧。在某些C编译器中,可以使用编译器标志来消除此开销,这会将某些类型的递归(实际上是某些类型的尾调用)转换为跳转而不是函数调用。 (source

答案 2 :(得分:1)

对于这个特殊问题,没有太多的运行时差异。我个人宁愿使用迭代,我认为它会更简单,更容易理解,但我认为每个都是他自己的。

现在一些递归函数(例如递归Fibonacci数)应该通过迭代来完成,只是因为它们可以指数增长。

一般来说,我不使用递归,除非它会让我的问题更容易理解。

答案 3 :(得分:1)

您应该调查周边情况。对于大的递归,堆栈可能会溢出,那就是循环+1。

我不确定哪一个运行得更快但是相对容易衡量,将JIT和其他内容考虑在内。

代码维护方面:对于我们大多数人来说,理解和修复循环要比递归容易得多。开发人员的时间通常比轻微的性能差异更重要。

答案 4 :(得分:1)

取决于上下文。例如,如果我有一个Composite对象树(在SWT中)并且您希望遍历它们,最简单的方法是使用这样的递归:

    private boolean checkControlParent(Composite comp) {
        boolean ret = false;
        if (comp != null) {
            if (this.equals(comp)) {
                ret = true;
            } else {
                ret = checkControlParent(comp.getParent());
            }
        }
        return ret;
    }

否则,如果性能很重要,请注意,由于函数/方法调用开销,递归调用在大多数情况下比简单循环慢。

所以最重要的是,如果你需要遍历递归是一个自然解决方案的对象,并且你没有冒险StackOverflowError继续使用递归。否则你可能最好用循环。

还有一件事:递归方法有时往往难以阅读,理解和调试。