void quickSort(int *a, int beg, int end)
{
int pivotLoc;
if (beg < end)
{
partitionArray(a, beg, end, &pivotLoc);
quickSort(a, beg, pivotLoc - 1);
quickSort(a, pivotLoc + 1, end);
}
}
何时调用第二个递归语句?
第一条递归语句何时退出?
我在多个递归语句调用中花了很多时间。
您能详细说明一下吗?
答案 0 :(得分:1)
现在让我们举一个小例子来了解递归。
假设您在以下数组上以以下方式调用quickSort
:
int a = {3,1,4,2,5};
quickSort(a,0,4);
现在,让我们开始跟踪。
quickSort(a,0,4)
。 pivotLoc
。beg<end
,其中beg = 0
和end = 4
(在步骤1中通过它们)。partitionArray(a,0,4,address_of_pivotLoc);
的函数partitionArray
函数后,已设置pivotLoc
变量的值。quickSort(a, 0, pivotLoc-1)
,它从第一步开始再次重复,除了end
不是 4 ,而是pivotLoc-1
。何时调用第二个递归语句?
答案:当条件beg<end
在第一次递归调用中失败时,它将返回。这是第二个递归调用从第一个递归的 last 调用开始执行的时间(即,从第一个递归没有失败条件{{ 1}})。
第一条递归语句何时退出?
答案:当条件beg<end
失败时,它将到达函数的结尾并返回到 same 函数的上一个调用。然后第二个递归调用开始。
TLDR;基本上,使beg<end
调用中的任何结束的条件是quickSort
条件if
。
答案 1 :(得分:1)
这个问题可以一概而论:
void f()
{
f() // 0
f() // 1
// ...
f() // n
}
如果从中绘制调用图,我们(当然)会得到树状结构:
f()
/ / \
/(0) /(1) .... \(n)
f() f() f()
每个进一步的递归调用将在相应父调用下方的树上方重复。树不需要平衡,即。 e。从根到不同叶子的路径长度可能会有所不同。如果递归调用在条件分支内,则甚至所有非离开节点也不需要具有相同数量的子代。
现在,如果我们有两个紧随其后的任意两个函数调用f(); g();
,则只有在g
返回时才能调用f()
。当然,这也适用于随后的两个递归调用,这又意味着,调用树必然像深度优先搜索中那样走动。
回到您的quicksort示例(为简单起见,忽略分区不需要将两个相等的一半分成两半),那么每个子数组的后一半将仅在前一半完成后才进行排序。全局查看:
sort first half
sort first quarter
sort first eighth
sort second eighth
sort second quarter
sort third eighth
sort fourth eighth
sort second half
sort third quarter
// ...
sort fourth quarter
// ...