0

代码是这样的:

void insertNode(TreeNode **root, COMPARE compare, void* data) {
    TreeNode *node = (TreeNode *)malloc(sizeof(TreeNode));

    node->data = data;
    node->left = NULL;
    node->right = NULL;

    if(*root == NULL) {
        *root = node;
        return;
    }

    while(1){
        if(compare((*root)->data, data) > 0) {
            if((*root)->left != NULL) {
                *root = (*root)->left;
            } else {
                (*root)->left = node;
                break;
            }
        } else {
            if ((*root)->right != NULL) {
                *root = (*root)-> right;
            } else {
                (*root) -> right = node;
                break;
            }
        }
    }
}

指针从不使用 likeroot并且始终用作(*root). 不是TreeNode **root多余吗?是否可以将它的参数减少到TreeNode *root函数体中的部分更改为root仅从(*root). 如果不是为什么?

4

5 回答 5

1

不,这不是多余的。C 是一种严格的按值传递语言,如果您想更改传入的参数(相信我),C 会使用指针模拟按引用传递。

在您的情况下,您想要更改 type 的变量TreeNode *,因此您需要将指针传递给该变量,这就是您有双重间接的原因。

不要被您似乎已经有一个指针的事实所迷惑,在您的情况下,它在概念上与以下内容相同:

void changeInt (int *pXyzzy) { *pXyzzy = 42; }

除了那是为了改变一个int. 如果你想改变一个int *,你需要:

int some_int = 42;
void changeIntPtr (int **ppXyzzy) { *ppXyzzy = &some_int; }

注意增加的间接级别。这更类似于您所需要的,因为您正在更改指向某物的指针(因此您需要一个指向它的双指针)。

如果不通过 传入&some_treenode_pointer_variable和设置它*some_treenode_pointer_variable = something,更改的值永远不会找到返回给调用者的方式(该变量是按值传递的,只是一个本地副本)。

检查以下代码及其输出可能会有所帮助。方法 1 尝试通过简单地设置来更改指针,方法 2 使用指针到指针的方法来尝试更改它:

#include <stdio.h>

static int someInt;

static void method1 (int *pXyzzy) {
    printf ("Pointer on calling method1    = %p\n", pXyzzy);
    pXyzzy = &someInt;
    printf ("Pointer on exiting method1    = %p\n", pXyzzy);
}

static void method2 (int **ppXyzzy) {
    printf ("Pointer on calling method2    = %p\n", *ppXyzzy);
    *ppXyzzy = &someInt;
    printf ("Pointer on exiting method2    = %p\n", *ppXyzzy);
}

int main (void) {
    int *plugh = NULL;

    printf ("Pointer in main on start      = %p\n", plugh);
    method1 (plugh);
    printf ("Pointer in main after method1 = %p\n", plugh);
    method2 (&plugh);
    printf ("Pointer in main after method2 = %p\n", plugh);

    return 0;
}

输出是:

Pointer in main on start      = 0x0

Pointer on calling method1    = 0x0
Pointer on exiting method1    = 0x404018
Pointer in main after method1 = 0x0

Pointer on calling method2    = 0x0
Pointer on exiting method2    = 0x404018
Pointer in main after method2 = 0x404018

您可以看到,虽然局部变量的值在方法 1 中发生了更改,但并没有反映回调用者main。方法 2确实将更改反映给调用者。


顺便说一句,您不应该malloc在 C 中转换返回值:

TreeNode *node = (TreeNode *)malloc(sizeof(TreeNode));

它可以隐藏某些细微的错误,并且完全没有必要,因为 C 显式转换void *为其他指针类型。更好地使用:

TreeNode *node = malloc (sizeof (TreeNode));

您还应该检查返回值malloc以确保您没有NULL返回,以免出现以下行:

node->data = data;

会给你带来无尽的悲伤。

于 2014-07-28T04:14:54.097 回答
1

如果原始树为空,则根 = NULL。

当用户调用

TreeNode* tree = NULL;
insertNode(&tree, compare, data);

他们期望树成为根节点。

如果传递的是树而不是&tree,则指针是按值传递的,并且您无法使树变量指向新创建的节点。(因为你不知道树的地址。在函数中,你得到的只是一个NULL,所以你不能改变它的值)

于 2014-07-28T04:18:53.577 回答
0

it seems that purpose of line "*root = node;" is to make *root as root node of tree but at later stage during traversal root node is modified (*root = (*root)->left; *root = (*root)-> right) which seems incorrect, i think temporary node should be used for traversal.

于 2014-07-28T04:46:19.440 回答
0

一点也不。除非参数是指向指针的指针,否则该行*root = ...无法工作。

于 2014-07-28T04:15:29.657 回答
0
if(*root == NULL) {
        *root = node;
        return;
}

就是说:如果root指向NULL,就给 赋值root。如果您收到一个TreeNode *pby 参数,并且p == NULL,您不能为 p 分配任何东西以使其对调用者产生影响。

该函数可以与指向空变量的指针一起使用,并且在返回后它将具有TreeNode *不指向的有效值NULL

请记住:C 通过复制接收所有值,如果要修改参数,则应该接收指向该参数的指针。如果要修改 a TreeNode *,则应通过 aTreeNode **

于 2014-07-28T04:18:38.433 回答