Algorithm 数组中的基本递归搜索算法
我在递归方面有很多问题,包括它背后的逻辑。我知道,原则上每次我们有一个循环时,我们都可以用对函数的调用来替换它。所以我尝试了一个非常经典的简单示例,搜索表中的最大值。以下是java中迭代的经典示例: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) {
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;
}