【问题标题】:Understanding execution of recursion in tree traversal了解树遍历中递归的执行
【发布时间】:2016-08-24 07:36:22
【问题描述】:

我在理解树遍历中的递归执行时遇到问题。

 void travel (Node *tree)
 { 
     if(tree!=NULL)
     {
         printf("%d ",tree->info); 
         travel(tree->left);
         travel(tree->right);
      }
 }

你能解释一下吗

      1
   2     3
 4     5   6

输出:1 2 4 3 5 6

达到4后会发生什么。编译器如何忽略travel(tree->left)以及它如何回到1并达到3。

我的确切问题是函数调用 travel(tree->left) 是如何被忽略的?

【问题讨论】:

    标签: recursion tree tree-traversal


    【解决方案1】:

    一切都是为了从函数中返回。

         void travel (Node *tree)
     { 
         if(tree!=NULL)
         {
             printf("%d ",tree->info); 
             travel(tree->left);
             travel(tree->right);
          }
     }
    
    
          1
       2     3
     4     5   6
    

    在上面的函数中,只要有一个孩子要走,它就会走左边的路。如果它没有找到左孩子,则尝试右孩子。如果没有找到正确的孩子,则返回该函数。直到我们到达节点“4”,我们还没有处理函数的单个返回。一旦我们在 4 处,我们看到没有更多的左孩子,所以我们尝试右孩子,但也没有右孩子。所以我们将函数返回到我们被调用的地方。那恰好是 2。所以我们将从 2 处离开的地方继续。在 2 处,我们通过调用 travel(tree->left); 指令走左边的路径,现在我们从这条指令返回,我们现在将继续下一条指令是travel(tree->right);,唉,没有正确的孩子,所以我们从我们开始的地方返回函数..恰好是travel(tree->right);行的节点1,现在轮到下一行travel(tree->right);,因此我们到达3。

    希望你能关注。

    【讨论】:

    • 感谢您的回复。 “”一旦我们到了 4 岁,我们就会看到没有左孩子了,所以我们尝试右孩子,但也没有右孩子。 "" 这里编译器如何知道没有孩子在那里,因为左右节点只是一个函数参数不是吗???我的意思是检查是否有右孩子或左孩子缺席的条件,那它是怎么发生的?
    • 嗨,在这个 C 代码中 tree 是一个指向结构的指针(比如 JS 中的构造函数),它的 left 和 right 属性也是相同方式的指针。您只需将此指针传递给travel 之类的travel(tree->right) 函数即可处理传递的参数指向的节点。在这种情况下,处理节点意味着指令printf("%d ",tree->info);。处理完成后,您将再次调用自身内部的相同旅行函数,并将下一个节点作为参数传递。更多关于 C 指针fredosaurus.com/notes-cpp/structs/arrow.html
    【解决方案2】:

    首先我假设你知道程序何时进入一个函数,直到它结束才退出它。之后,让我们去分析代码及其执行。

    由于 if 语句中的 NULL 条件,我假设您正在使用指针,并且每个元素都有两个指向左右子节点的指针,也可以为 null。

    首先,您的函数分析第一个元素(数字 1)并检查是否为空,如果不是,则输入 if 语句,打印其值并转到其左孩子,重复该过程,检查是否为 4为空,如果不是,则在 if 语句中输入它的值并转到其左孩子,这是递归魔术发生的情况,当元素 4 的孩子为空时,函数返回并且不继续递归。之后返回到第4个元素的层级,检查右孩子,因为它为null返回第1层,知道检查第1个右孩子,照常继续。

    你必须想象像递归一样的关卡,当你在一个完成时返回到上一个,并继续正常执行,直到没有更多的递归。

    希望对你有帮助,如果你什么都不懂,请原谅我的英语。

    【讨论】:

    • 感谢回复“”当元素4的子元素为null时,函数返回,不再继续递归“”。你能单独解释这一点吗。关于左孩子的检查在哪里为空???
    • 首先编译器不检查那个。它发生在运行时。元素 4 有两个指针:leftChild 和 rightChild,即使它们为空。当使用 leftChild 调用该函数时,它检查是否为 null,并且由于元素 4 没有子元素,因此它为 null,因此它返回到第 4 级并检查右子元素并重复。一旦它检查了它的所有子函数,函数就会退出 if 语句并上升到第 2 级并重复。
    • 感谢您的回复。因此,如果不是递归,而是假设它只是一个函数调用。像 func(tree->left)。因此,如果在达到 4 后调用此函数,则函数在参数中获取值 NULL 并开始执行不是吗???这是正常的执行方式。那么递归如何有特权在运行时检查null呢?
    • 当它得到第4个左孩子并检查它是否为空时,它不进入if语句并返回第4层,然后它检查右孩子,并再次检查它是否为空值。一旦它完成了第 4 个孩子,它就会上升到第 2 级并继续执行。你必须把它想象成更深的东西,直到退出条件(在这种情况下,当一个孩子为空)成真,在那一刻它上升并尝试另一个路径重复这个过程,直到没有更多可能的路径。
    猜你喜欢
    • 2014-12-21
    • 1970-01-01
    • 1970-01-01
    • 2022-11-21
    • 2018-07-12
    • 2014-03-11
    • 1970-01-01
    • 2017-05-11
    • 1970-01-01
    相关资源
    最近更新 更多