簡體   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