多个递归语句调用

时间:2018-12-16 06:22:02

标签: c recursion quicksort

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);
  } 
}

何时调用第二个递归语句?

第一条递归语句何时退出?

我在多个递归语句调用中花了很多时间。

您能详细说明一下吗?

2 个答案:

答案 0 :(得分:1)

现在让我们举一个小例子来了解递归。

假设您在以下数组上以以下方式调用quickSort

int a = {3,1,4,2,5};
quickSort(a,0,4);

现在,让我们开始跟踪。

  1. 首先,您将致电quickSort(a,0,4)
  2. 然后此调用声明局部变量pivotLoc
  3. 然后您检查条件beg<end,其中beg = 0end = 4(在步骤1中通过它们)。
  4. 现在您调用名为partitionArray(a,0,4,address_of_pivotLoc);的函数
  5. 返回partitionArray函数后,已设置pivotLoc变量的值。
  6. 现在您呼叫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
      // ...