递归过程

问题描述 投票:0回答:3

我的问题是关于递归,我很难理解一点。我调试了一小段代码,我知道流程是如何工作的,但是问为什么以及如何?我会解释我的怀疑。

我知道这可能是一个愚蠢的问题,但请清楚我。

检查代码 - :

#include <stdio.h>

void sum(int n);
void add(int number);

int main()
{
    int number, result;

    printf("Enter a positive integer: ");
    scanf("%d", &number);
    sum(number);
}

void  sum(int num)
{
    if (num!=0) {
        sum(num - 1); //(2-1) (1-1)
        sum(num - 1); // (1-1) (2-1)
        add(num);
    }

}

void add(int number){
    int a = 5;
    int c = 0;
    c = a+number;

    printf("%d ",c);
}

当我给用户输入2时,流程转到if条件 - > Valiadte - >进入内部 - >首先调用sum(2-1) - >再次上升 - >验证 - >首先调用sum(1-1) - >离开if - >调用第二个sum(1-1) - >走出if - >调用add函数 - >再次调用sum(2-1) - >验证if - >调用第一个sum(1-1 ) - >出去 - >再次调用第二个sum(1-1) - >调用add - >退出。

Recursion定义说 - :当函数调用自身时它是递归的,递归继续,直到满足某些条件来阻止它。

我的问题是为什么第二笔被称为2次或更多次?我的意思是,如果你看到它在第一次调用时条件(1-1),所以它应该退出并且只是调用add,但是在调用add之后它再次用于(2-1)。第二个Sum是否以相反的顺序被调用?

是不是如果首先被称为123然后第二个必须去321甚至在它满足条件后?这是递归过程实际上如何工作?谁能解释这个概念?


我的问题稍微更新一下。我删除了第二个内部函数调用,现在剩下一个内部递归函数。检查更新的代码 - :

void sum(int num)
{

    if (num != 0) {
        sum(num - 1);
    }

    if (num==2) {
        printf("Back to memory address of 2 , you can exit out of function now ");
    }

}

Input = sum(2)。现在当sum gosum(1-1)sum(0) - >退出if。我看到电话没有结束功能。 num的值再次回到2 go(0->1>2) - >进入if (num==2) - >在控制台上打印 - >退出功能。

这表明了什么?如果我做出一个猜测就像 - :内部调用作为pass by value而不是reference?因此,甚至内部递归函数更新num的值它不会改变memory address仍然是2的值。

流程是这样的 - :

sum(2)实际内存地址值 - > sum(1)复制值 - > sum(0)复制值。好的,我现在可以出去了。

可是等等!!我无法退出功能,num必须返回并更新实际内存地址值 - :

num = 0 , num=1 , num=2(That's what I was looking for )。大!!没有功能。

那是怎么回事?我还是有点卡住了。

c recursion
3个回答
3
投票

添加一些简单的printf语句并跟踪全局depth变量中的“调用深度”,可以很好地表示正在发生的事情:

int depth = 0;
void sum(int num)
{
    for(int i = 0; i < depth; ++i) printf("\t");
    printf("-> sum | depth: %d | num: %d\n", depth, num);
    ++depth;

    if (num != 0) {
        sum(num - 1);
        sum(num - 1);
        add(num);
    }

    --depth;
}

输入2

-> sum | depth: 0 | num: 2
    -> sum | depth: 1 | num: 1
        -> sum | depth: 2 | num: 0
        -> sum | depth: 2 | num: 0
        add: 6
    -> sum | depth: 1 | num: 1
        -> sum | depth: 2 | num: 0
        -> sum | depth: 2 | num: 0
        add: 6
    add: 7

你也可以在sum的末尾打印,看看退出函数的时间:

-> sum | depth: 0 | num: 2
    -> sum | depth: 1 | num: 1
        -> sum | depth: 2 | num: 0
        <- sum | depth: 2 | num: 0
        -> sum | depth: 2 | num: 0
        <- sum | depth: 2 | num: 0
        add: 6
    <- sum | depth: 1 | num: 1
    -> sum | depth: 1 | num: 1
        -> sum | depth: 2 | num: 0
        <- sum | depth: 2 | num: 0
        -> sum | depth: 2 | num: 0
        <- sum | depth: 2 | num: 0
        add: 6
    <- sum | depth: 1 | num: 1
    add: 7
<- sum | depth: 0 | num: 2

live example on wandbox


2
投票

这是因为您不修改该值

void  sum(int num)
{
    if (num!=0) {
        sum(num - 1); //(2-1) (1-1) mark this as call [a]
        sum(num - 1); // (1-1) (2-1) mark this as call [b]
        add(num);
    }
}

当你打电话给sum(2)时:

  • 函数调用sum(1)at [a]
  • 并且因为1不是0,所以它再次以递归的方式调用[a]处的sum(0)
  • 你不修改数字,这就是为什么再次调用[b]的sum(0)
  • 然后添加(1)调用,
  • 当它返回时,你刚刚在[a]调用时完成了sum(1)
  • 现在你在[b]处调用sum(1),因为变量num仍然是2并且它没有被前一次调用修改
  • 等等

-1
投票

正如你所知,sum永远不会终止(如果你摆脱了第二次递归调用),输入为2,调用序列是:调用sum与2 if if计算为true所以第一个sum用参数调用1 if再次为true所以第一个sum现在被调用,参数为0,if if计算为false所以现在第二个和被调用参数-1第一个如果求值为true所以第一个和被调用参数为-2首先,如果计算结果为true,则第一个总和用-3来调用。我真的不明白你为什么要第二次打电话。

© www.soinside.com 2019 - 2024. All rights reserved.