Algorithm 数组中的基本递归搜索算法

Algorithm 数组中的基本递归搜索算法,algorithm,recursion,Algorithm,Recursion,我在递归方面有很多问题,包括它背后的逻辑。我知道,原则上每次我们有一个循环时,我们都可以用对函数的调用来替换它。所以我尝试了一个非常经典的简单示例,搜索表中的最大值。以下是java中迭代的经典示例: static void rechercheMax(int unTab []) { int max = unTab[0]; for (int j = 0; j < unTab.length; j++) { if (unTab[j] > max) {

我在递归方面有很多问题,包括它背后的逻辑。我知道,原则上每次我们有一个循环时,我们都可以用对函数的调用来替换它。所以我尝试了一个非常经典的简单示例,搜索表中的最大值。以下是java中迭代的经典示例:

static void rechercheMax(int unTab []) {
    int max = unTab[0];

    for (int j = 0; j < unTab.length; j++) {
        if (unTab[j] > max) {
            max = unTab[j];
        }
    }
    System.out.println("the  max is " + max);
}
你能给我解释两件事吗

  • 为什么它不能给出正确的结果,以及
  • 为什么会朝相反的方向发展

这种行为使我很不安;恐怕我对递归一无所知。

它没有给出正确的结果,因为您忘记了使用递归调用返回的值。事实上,您应该将它分配给
max
(这样它就会由函数中的最后一条语句返回),或者直接返回它

它(也)走向相反的方向,因为这是递归的回溯部分:首先它潜入更深的递归级别(向前),然后它到达最深的点(当
if
条件不再为真时),然后开始从结束返回到开始。这是一个原则。这是先进先出(FILO)的处理顺序。所以在“入”部分(递归)你得到的是正向顺序,而在“出”部分(回溯)你得到的是相反的顺序

请注意,您实际上不需要更改代码中的变量,如
j++
max=
。您可以直接将更改后的值作为参数传递给递归调用:

static int rechercheMaxRec(int[] unTab, int j, int max) {   
    if (j < unTab.length) {
        if (unTab[j] > max) {
            return rechercheMaxRec(unTab, j+1, unTab[j]);
        }else {
            return rechercheMaxRec(unTab, j+1, max);             
        }
    }
    return max;
}
即使在三元运算符的帮助下,也可以减少:

static int rechercheMaxRec(int[] unTab, int j, int max) {   
    return j < unTab.length ? rechercheMaxRec(unTab, j+1, Math.max(max, unTab[j])) : max;
}
static int rechercheMaxRec(int[]unTab,int j,int max){
返回j
Re“为什么它不能给出正确的结果”

使用递归,进行初始递归调用,它本身进行第二次调用,等等。初始调用将返回嵌套调用返回的结果,嵌套调用本身将返回其嵌套调用返回的结果,等等

您在此处的调用未返回正确结果的原因是您调用了
rechercheMaxRec(unTab,0,0),它调用
rechercheMaxRec(unTab,j,max),但不返回其结果。因此,当您调用
rechercheMaxRec(unTab,0,0)时会发生什么,它计算
if(j
true
,然后计算
if(unTab[j]>max)
true
,然后运行
max=unTab[j](即将
max
设置为7),然后调用
rechercheMaxRec(unTab,1,7)但不返回由<代码>rechercheMaxRec(unTab,1,7)返回的值。因此,在调用rechercheMaxRec(unTab,1,7)之后,代码退出条件块并调用
return max,即返回7

因此,基本上您想要的是替换
rechercheMaxRec(unTab,j,max)带有
返回rechercheMaxRec(unTab,j,max)。这将返回103而不是7

还有一个问题不会影响您仅查找
untab
最大值的能力,但如果您向代码中添加了更多内容,则可能会导致其他问题
untab
的长度为18,因此如果j==17,代码将增加j,然后调用
rechercheMaxRec(untab,18,max),超出范围。同样,这不会导致代码出现错误,但如果您尝试
System.out.println(…)
untab[j]
的值,则会抛出错误

避免这种情况的方法是在递增
j
之后,再次检查
j
,如果是,则调用
rechercheMaxRec(unTab,j,max)
,如果不是,则返回
max
,因为您位于数组的末尾

下面是解决这两个问题的代码:

static int rechercheMaxRec(int[] unTab, int j, int max) {
    if (j < unTab.length) {
        if (unTab[j] > max) {
            max = unTab[j];
            j++;
            if (j < unTab.length) {
                return rechercheMaxRec(unTab, j, max);
            } else {
                return max;
            } 
        }else {
            j++;
            if (j < unTab.length) {
                return rechercheMaxRec(unTab, j, max);
            } else {
                return max;
            }       
        }
    } 
    return max;
}
static int rechercheMaxRec(int[]unTab,int j,int max){
如果(j最大值){
max=unTab[j];
j++;
如果(j
Re:为什么会朝相反的方向发展?

我不认为它是:)我认为它可能看起来像是这样,因为它返回了7而不是103,但这只是因为上面讨论的调用vs返回的概念


如果有什么不清楚,请告诉我

非常感谢您宝贵的意见和建议。我在最后几天没空。刚才问题已经解决了,然而,我仍然有很多困难去理解递归。你知道有什么书或网站可以让我做更多的练习吗。谢谢你的帮助。
static int rechercheMaxRec(int[] unTab, int j, int max) {   
    return j < unTab.length ? rechercheMaxRec(unTab, j+1, Math.max(max, unTab[j])) : max;
}
static int rechercheMaxRec(int[] unTab, int j, int max) {
    if (j < unTab.length) {
        if (unTab[j] > max) {
            max = unTab[j];
            j++;
            if (j < unTab.length) {
                return rechercheMaxRec(unTab, j, max);
            } else {
                return max;
            } 
        }else {
            j++;
            if (j < unTab.length) {
                return rechercheMaxRec(unTab, j, max);
            } else {
                return max;
            }       
        }
    } 
    return max;
}