【问题标题】:multiple recursion多重递归
【发布时间】:2011-09-26 04:43:34
【问题描述】:

我有一个疑问,在一个块内,如果同一个函数被递归调用两次或两次以上,那么执行的顺序是什么?

例如:在合并排序的情况下,如果我这样做,则进行分区

mergesort(int a[], int low, int high)
{
int mid;
if(low<high)
{
mid=(low+high)/2;
mergesort(a,low,mid);
mergesort(a,mid+1,high);
merge(a,low,high,mid);
}

那么 (1)如果条件(低

(2) 或者对 merge(a,low,mid) 的调用会递归进行,然后在 merge(a,mid+1,high) 递归执行后,最后是 merge(a,low,mid)被执行。

我知道这对你们这些技术熟练的人来说很简单,但请回答这个问题,帮我一个忙。

【问题讨论】:

    标签: c++ c


    【解决方案1】:
                            merge_main_call_0
                                  |
                                  |
                  +-----------------+------------------+
                  |                                    |
                  +                                    +
           merge_1_call_1                         merge_2_call_4
                  +                                    +
                  |                                    |
        +---------+---------+                +---------+---------+
        |                   |                |                   |
        +                   +                +                   +
     merge_1_call_2   merge_2_call_3     merge_1_call_5    merge_2_call_6
     (here `if' is false)                     (here `if' is false) 
    

    这显示了调用树。每当if 在某个级别或递归为真时,将首先调用第一个函数。当if 在某个级别或递归中为假时,它将返回到最后一个函数调用(调用它的那个),这将在第一个函数调用之后开始执行,这将调用第二个函数。然后第二个函数重复同样的事情。

    上图中merge_1_call_n表示第n次调用合并函数1。

    if 的条件第一次在某个递归级别变为假时,它将返回到最后一个递归级别并从它离开的地方开始执行,然后调用第二个函数。同理,递归到本层该函数调用将返回时,执行合并函数,然后控件从本层返回到上一个递归层。

    了解什么是递归级别非常重要。为此,将第一个函数调用绘制为 n 叉树的最左边的孩子,将最后一个调用绘制为最右边的孩子,并尝试形成树状结构。深度优先搜索(预购)会产生函数的调用顺序。

    更新

    对于正在进行的递归调用过程,请查看Call StackActivation Records

    【讨论】:

    • 递归树对理解递归非常有帮助。
    【解决方案2】:

    在您的示例中,如果 low &lt; high,则 mergesort() 函数将被调用两次merge() 函数将被调用一次。然而,由于这个函数是递归的,对mergesort() 的调用可能会调用自己更多次(取决于传递给它的值)。

    【讨论】:

    • :谢谢。你能告诉我函数的调用顺序吗?它们将如何执行?我对递归有误解。如果你能解决我的疑问,那将是非常好的在堆栈机制或任何其他递归实现机制的帮助下。或者,如果你可以请给我链接以消除我对递归的疑虑。
    • @aamir: 你能告诉我什么是推入堆栈的参数,返回值等吗?请解释一下。
    • @gautam kumar:它们实际上并没有被压入,通过操作基指针寄存器和指向新堆栈帧的堆栈指针寄存器来创建一个新的堆栈帧。你应该看看函数激活记录:enel.ucalgary.ca/People/Norman/engg335_fall1998/activ_rec
    • @phoxis:请回答问题的最后一部分,即“当 if 条件为真时,所有三个函数将被一个一个调用或调用第一个函数,即 mergesort(a,low, mid) 将被重复调用。请清除我的疑问。”
    【解决方案3】:

    两次函数调用意味着该函数将被调用两次,如果条件为真。

    【讨论】:

    • :谢谢。你能告诉我函数的调用顺序吗?它们将如何执行?我对递归有误解。如果你能解决我的疑问,那将是非常好的在堆栈机制或任何其他递归实现机制的帮助下。或者,如果你可以请给我链接以消除我对递归的疑虑。
    • 第一个会先被调用。第二个将被称为第二个。任何其他调用都发生在单独的堆栈帧中。
    【解决方案4】:

    这是@phoxis 答案的扩展,显示了调用堆栈(正如他在回答中提到的那样)。我认为理解调用堆栈是理解树的方法:

    【讨论】:

      【解决方案5】:

      在主合并函数中,如果 if 条件为真,则首先调用 merge()。编译器将所有内容保存在堆栈中并再次调用主合并。它一直重复这个直到 if 条件为假。一旦 if 条件为假,编译器就会通过从堆栈中弹出来撤退。它将不断从堆栈中弹出,直到返回到堆栈中保存的第一个 merge()。弹出并调用此合并后,它将继续进行第二次合并并重复整个过程。与上次合并类似。

      所以顺序是: 第一次合并,然后继续重复直到 if 失败,第二次合并,继续重复...,第三次合并

      【讨论】:

      • 你是对的..我的解释是错误的!我想我现在应该睡觉了
      猜你喜欢
      • 2011-11-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-23
      • 1970-01-01
      相关资源
      最近更新 更多