繁体   English   中英

带有指针的二叉树递归插入

[英]binary tree recursive insertion with pointer to pointer

void insert(node ** tree, int val)
{
    node *temp = NULL;
    if(!(*tree))
    {
        temp = (node *)malloc(sizeof(node));
        temp->left = temp->right = NULL;
        temp->data = val;
        *tree = temp;
        return;
    }

    if(val < (*tree)->data)
    {
        insert(&(*tree)->left, val);
    }
    else if(val > (*tree)->data)
    {
        insert(&(*tree)->right, val);
    }
}

此函数使用指向指针node ** tree指针来表示二叉树的头。 我在许多教程和网站上都遇到了相同的方法。 我想知道为什么每个人都坚持使用指针指向指针,为什么不只是使用“ node * tree”。 我认为即使指向树头的指针也能很好地完成工作,而仅使用指向树头的指针,递归调用将如下所示(如果我错了,请纠正我):

insert(tree->left, val); // assuming definisiton as void insert(node *tree, int val);

要么

insert(tree->right, val); // assuming definisiton as void insert(node *tree, int val);

如果我的理解是错误的,请纠正我。 我是新手。 谢谢。

请记住,在C中,参数是通过value传递 ,这意味着将作为参数传递的表达式的值复制到函数中。 因此,如果您在函数内更改参数,则仅更改副本,并且该更改将对调用者不可见(即更改丢失)。

为了克服该问题,您可以通过传递指针来模拟按引用传递。 如果要更改指针,则必须将指针传递给该指针。

如果查看insert函数,您会发现当*treeNULL (即没有节点)时,它会分配给指针。 如果您没有将指针传递给指向节点的指针,那将不起作用。


愚蠢的例子:

#include <stdio.h>

void func1(const char *s)
{
    s = "hello from func1";
}

void func2(const char **s)
{
    *s = "hello from func2";
}

int main(void)
{
    const char *s1 = "foo";
    const char *s2 = "bar";

    func1(s1);   /* Passing pointer by value */
    func2(&s2);  /* Passing pointer by "reference" */

    printf("s1 = \"%s\"\n", s1);
    printf("s2 = \"%s\"\n", s2);
}

上面的小示例程序将打印

s1 = "foo"
s2 = "hello from func2"

这是因为tree可以为空( NULL )。 在这种情况下,您可以设置外部指针使其指向新的根。

node *root = NULL;
insert(root, 10);

传递给函数的两种类型:

1.按值传递=创建值的副本。 函数终止后,对该值的任何更改都将丢失。

2.通过引用传递=不会创建副本,但指向要传递的值。 如果发生更改,则值将更改。

双指针(**)指向单个指针(*)的地址。 因此,如果将单指针传递给函数,则需要使用双指针来更改单指针的值(地址)。 否则,没有任何变化。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM