这个递归函数有什么作用?

时间:2012-06-29 15:13:06

标签: java recursion

这个功能有什么作用?你如何评价呢?

如何追踪?如何理解递归方法?

我只是无法理解递归,考试日期即将到来,我知道为了理解递归,我必须先了解递归。

但我不能写一个稍微复杂的递归方法,任何人都可以帮我用最简单的英文单词。

public class BalancedStrings {

    public static void printBalanced(String prefix, int a, int b) {
        if (a > 0)
            printBalanced(prefix + "a", a - 1, b);
        if (b > 0)
            printBalanced(prefix + "b", a, b - 1);
        if (a == 0 && b == 0)
            System.out.println(prefix);
    }

    public static void printBalanced(int n) {
        if (n % 2 == 0) {
            printBalanced("", n / 2, n / 2);
        }
    }

    public static void main(String[] args) {
        printBalanced(4);
    }
}

4 个答案:

答案 0 :(得分:6)

printBalanced()的调用是递归调用。识别递归的方法是函数调用自身。使用树绘制时最好理解递归:

enter image description here

树的分支将继续创建更多功能,直到满足结束条件,在这种情况下为a == 0 && b == 0。您提供的函数看起来像是以递归方式打印与指定数量的“a”和“b”字符串联的字符串“prefix”。当变量ab到达0时,递归停止,结果将使用System.out.println(prefix);打印

在main函数中,您将整数4传递给printBalanced(int n),其中调用printBalanced(String prefix, int a, int b)的参数如下:printBalanced("",2,2);

整体结果是前缀与a和b的平衡数字连接

答案 1 :(得分:0)

你的停止状况是那个

a == 0 & b == 0

在满足此条件之前,您递归调用该函数并降低a和b,直到它们都为0。

尝试将一些断点放入printBalanced()中,这样你就可以看到它是如何工作的。

答案 2 :(得分:0)

在最基本的计算机科学意义上,递归是一种自我调用的函数。 递归的实际用法很少。

树遍历
图表
Lexing / Parsing
排序

递归的基本思想是你把原始问题分成更小(更容易解决)的自身实例,解决那些较小的实例(通常再次使用相同的算法),然后将它们重新组合成最终的解决方案。

例如,考虑以下计算数字阶乘的C代码

function factorial(int n)
{
  int fact = 1;
  for( int i = 2; i <= n; i++)
  {
    fact = fact * i;
  }
  return fact;
}

答案 3 :(得分:0)

通过在每次调用printBalanced之前放置print语句并将print语句作为每个printBalanced方法定义的第一行,可以帮助您查看递归。见下文:

public class BalancedStrings {

    public static void printBalanced(String prefix, int a, int b) {
        System.out.println( "printBalanced called prefix = " + prefix + " a = " + a + " b = " + b );
        if (a > 0) {
            System.out.println( "printBalanced calling printBalanced with prefix = " + prefix + " a-1 = " + (a-1) + " b = " + b );
            printBalanced(prefix + "a", a - 1, b);
        }
        if (b > 0) {
            System.out.println( "printBalanced calling printBalanced with prefix = " + prefix + " a = " + a + " b-1 = " + (b-1) );
            printBalanced(prefix + "b", a, b - 1);
        }
        if (a == 0 && b == 0)
            System.out.println(prefix);
    }

    public static void printBalanced(int n) {
        System.out.println( "printBalanced called n = " + n );
        if (n % 2 == 0) {
            printBalanced("", n / 2, n / 2);
        }
    }

    public static void main(String[] args) {
        printBalanced(4);
    }
}

此外,printBalanced也被称为重载方法,因为它有两个“方法签名”,这基本上意味着它被定义不止一次,每个方法定义都有一组不同的传递给方法的变量。 / p>

基本上,printBalanced将继续调用自己,直到变量a和b递减为零。然后它将打印出它不断累积的结果前缀。

此外,所有这些魔法都可能发生,因为每个方法调用都会将前缀a和b的当前状态推送到调用堆栈。然后,当方法最终返回而不进行递归调用时,堆栈将被展开。

我希望这有帮助!递归可能很难理解。您还可以通过自己玩计算机并通过执行在纸上记下将被推入调用堆栈的前缀,a和b的值的方法来手动跟踪调用。

这是包含跟踪打印的程序输出:

C:\Users\>java BalancedStrings
printBalanced called n = 4
printBalanced called prefix =  a = 2 b = 2
printBalanced calling printBalanced with prefix =  a-1 = 1 b = 2
printBalanced called prefix = a a = 1 b = 2
printBalanced calling printBalanced with prefix = a a-1 = 0 b = 2
printBalanced called prefix = aa a = 0 b = 2
printBalanced calling printBalanced with prefix = aa a = 0 b-1 = 1
printBalanced called prefix = aab a = 0 b = 1
printBalanced calling printBalanced with prefix = aab a = 0 b-1 = 0
printBalanced called prefix = aabb a = 0 b = 0
aabb
printBalanced calling printBalanced with prefix = a a = 1 b-1 = 1
printBalanced called prefix = ab a = 1 b = 1
printBalanced calling printBalanced with prefix = ab a-1 = 0 b = 1
printBalanced called prefix = aba a = 0 b = 1
printBalanced calling printBalanced with prefix = aba a = 0 b-1 = 0
printBalanced called prefix = abab a = 0 b = 0
abab
printBalanced calling printBalanced with prefix = ab a = 1 b-1 = 0
printBalanced called prefix = abb a = 1 b = 0
printBalanced calling printBalanced with prefix = abb a-1 = 0 b = 0
printBalanced called prefix = abba a = 0 b = 0
abba
printBalanced calling printBalanced with prefix =  a = 2 b-1 = 1
printBalanced called prefix = b a = 2 b = 1
printBalanced calling printBalanced with prefix = b a-1 = 1 b = 1
printBalanced called prefix = ba a = 1 b = 1
printBalanced calling printBalanced with prefix = ba a-1 = 0 b = 1
printBalanced called prefix = baa a = 0 b = 1
printBalanced calling printBalanced with prefix = baa a = 0 b-1 = 0
printBalanced called prefix = baab a = 0 b = 0
baab
printBalanced calling printBalanced with prefix = ba a = 1 b-1 = 0
printBalanced called prefix = bab a = 1 b = 0
printBalanced calling printBalanced with prefix = bab a-1 = 0 b = 0
printBalanced called prefix = baba a = 0 b = 0
baba
printBalanced calling printBalanced with prefix = b a = 2 b-1 = 0
printBalanced called prefix = bb a = 2 b = 0
printBalanced calling printBalanced with prefix = bb a-1 = 1 b = 0
printBalanced called prefix = bba a = 1 b = 0
printBalanced calling printBalanced with prefix = bba a-1 = 0 b = 0
printBalanced called prefix = bbaa a = 0 b = 0
bbaa