【问题标题】:How does this recursion function in BST returns a linked list which is in-order?BST 中的这个递归函数如何返回一个有序的链表?
【发布时间】:2016-07-07 11:24:10
【问题描述】:

BST中的这个递归函数如何返回一个有序的链表?

给定:(结构)

typedef struct TreeNode
{
    struct TreeNode *left ;  //left child
    struct TreeNode *right ;     //right child
    struct TreeNode *next ;  //field for linked list in tree
    Data Node_info;             //info data in node
} TreeNode;

假设我们有一个数字为 3、2、4 的 BST。 (3 是根,2 是左孩子,4 是右孩子)

我有 2 个功能相同,它们从 BST 创建一个链表。我这里没能跟进递归,如果有人能帮我弄清楚,那就太棒了!

第一个函数:

void  what1(TreeNode **head, TreeNode *root)
{
     if(root == NULL) 
           return; 
     what1((head),root->right);
     root->next=(*head);
     (*head)=root;
     what1((head),root->left);
}

我的计算: 走到右子树,直到我们到达 null,返回,做 4->在 NULL 上的下一个点,在 4 上做头点,然后向左,返回到 4,返回再次到 1,现在 3->在 4 上的下一个点,然后在 4 上做头点,依此类推..

但是我仍然不了解其他函数何时“暂停”以及它们何时执行,这意味着我的计算不准确并且我无法正确跟进该函数,这意味着我在某些地方缺乏对递归的理解.

这是我完全不知道如何遵循它的第二个函数,它实际上做同样的事情。如果您可以帮助我使用这些功能中的任何一个,我将不胜感激,因为我正在尝试完全理解 BST 的递归。在我完全理解这一点之前,我会在这里发布很多关于此的问题。

TreeNode * what2(TreeNode *root)
{
    TreeNode *left = NULL, *right = NULL, *tmp = root;
    if (root != NULL) 
    {      
        left = what2(root->left);      
        right = what2(root->right);      
        root->next = right;      
        if (left != NULL)
        {
            tmp=left;  
            while (left->next != NULL)              
                left=left->next;         
            left->next=root;      
        }   
    } 
    return tmp;
}   

【问题讨论】:

  • 我理解正确吗?使用 what1 时,您以 "what1(&root,root)" 开头,其中 "root" 指向树的根,对吗?
  • @dercz 左边的参数是我们要建立的列表,右边的参数是 bst
  • 哦,是的,不能使用 &root 作为列表的头部,因为它会创建一个循环。我认为您可以将 Data 设置为 int,构造一些树,用正整数标记顶点并在每个“***->next”分配中添加一些 printf,例如用 "#define id_of(T) (T==NULL?0:T->Node_info)" 然后 "left->next=root; printf(" %d -> %d \n", id_of(left), id_of(root));"等等...加上在每个过程的开头添加有关调用的信息,例如“printf("what1(%d,%d)\n",id_of((*head)),id_of(root));" -- 这是我能想到的检查这些函数的最直接的方法。

标签: c recursion tree binary-search-tree


【解决方案1】:

第一个函数的工作原理是对的,基本上是从头到尾构建树。

要理解第二个,你需要注意的是它会在子树中创建一个列表,然后将两个列表组合起来。当您调用该函数时,会发生以下步骤:

  1. 获取仅从左侧节点创建的列表的头部
  2. 获取仅从右侧节点创建的列表的头部
  3. 通过将左链表的末尾设置为指向根节点来附加根节点,然后让根节点指向右链表的开头。

可以看到

1.

left = what2(root->left);

在您的示例中,这将简单地返回左侧节点,因为它是单独的,但是发生这种情况是因为左侧节点的 left->leftleft->right 为 NULL,所以它只返回 left

2.

right = what2(root->right);

这里发生了同样的事情,但使用了正确的节点。

3.

root->next = right;      
if (left != NULL)
{
    tmp=left;  
    while (left->next != NULL)              
        left=left->next;         
    left->next=root;      
} 

在这里,我们首先将root->next 设置为right,这样我们就基本上创建了列表的中间部分。然后,将tmp 设置为left,因为它将成为列表的头部(最左边,所以开始)。然后遍历左侧列表,直到我们可以将最后一个元素设置为root。这会创建一个从leftrootright 的连续列表,因此是有序的。

【讨论】:

  • 谢谢大卫。如果根有 (3 作为根,1 是左子树,2 是 1 的右节点,4 是右子树,代码将如何变化。1,2 将如何连接到根 3?因为当left->next = root被调用时,1如何连接2,2如何连接3?
  • @IlanAizelmanWS 然后它将首先构建左子树,它将从根节点 (1)、左节点 (NULL) 和右节点 (2) 构建列表,将它们结合起来给你1->2->NULL。它将构建正确的子树,即4->NULL,因为它本身没有子树。然后它结合这两个列表来创建3->4->NULL,然后是1->2->3->4->NULL。归根结底,你所做的只是每次调用what2() 都是相同的情况,但问题更小。
  • 我明白你在说什么。但是当我在纸上编写所有递归调用时,我没有遵循这个函数。 :(
【解决方案2】:

这是给what1的。

这里,headNode ** - 这意味着:

head   : is a : pointer to a pointer to TreeNode
*head  : is a : pointer to a TreeNode
**head : is a : TreeNode

现在,当 what1 从 main(或其他一些函数)调用它时,它的调用方式如下:

/* Suppose root points to root TreeNode in tree */

/* ll_head will point to first node in linked list */
TreeNode *ll_head = NULL;

/* Call what1 and pass address of ll_head so that
 * address of the first node in linked_list can be stored in ll_head
 */  
what1(&ll_head, root);

现在看看当what1(&llhead, root)(即what1(&ll_head, node 3))被调用时会发生什么:

what1(&ll_head, node 3) 被调用时,它会执行以下操作:

  1. 调用(&ll_head,节点 4)
  2. 对节点 3 进行一些处理
  3. 调用(&ll_head,节点 2)

让我们一一看看:

1.在节点 4

4->next = (*head) /* which right now is pointing to NULL */ 
(*head) /* which is ll_head in main */ = address of node 4 

所以,到现在为止:

4->next = NULL, and 
(*head) /* which is ll_head in main */ =  address of node 4

2。在节点 3 中处理

3->next = (*head) /* which right now is pointing to node 4 */
(*head) /* which is ll_head in main */ = address of node 3

所以,到现在为止:

4->next is NULL,
3->next = address of node 4, and
(*head) /* which is ll_head in main */  = address of node 3

3.在节点 2

2->next = (*head) /* which right now is pointing to node 3 */
3->next = address of node 4
4->next = NULL, and
(*head) /* which is ll_head in main */  = address of node 2

所以当 what1(*ll_head, node3) 返回时,这将是事物的状态:

ll_head = address of node 2
2->next = address of node 3
3->next = address of node 4
4->next = NULL

哪个是这个 BST 的有序链表。

【讨论】:

  • 感谢 SPS!我也是这么想的。我正在努力使用第二个功能 atm
猜你喜欢
  • 2018-05-23
  • 2011-02-04
  • 2012-04-24
  • 2010-10-09
  • 2021-07-25
  • 1970-01-01
  • 2022-01-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多