在C中将int与NULL进行比较 - 本教程是否正确?

时间:2016-11-20 00:25:16

标签: c

我正在查看本教程http://www.learn-c.org/en/Binary_trees,并在insert函数中将int与NULL进行比较。它似乎在tut网站上运行良好,但它对我不起作用,我的研究告诉我它应该不起作用。我的代码如下。

  1. 我在这里错了还是教程错了?
  2. 如果教程错误,有没有办法动态设置BST的第一个节点的值?我想过检查左右两者是否都为空,但这只会继续重置第一个节点。有一个节点值的第三个指针似乎很浪费但也许这是唯一的方法?

    #include <stdio.h>
    #include <malloc.h>
    struct bstNode {
        int val;
        struct bstNode *left;
        struct bstNode *right;
    };
    
    int insert(struct bstNode *head, int val);
    
    void printDFS(struct bstNode *head);
    
    int main() {
        struct bstNode *bstTree = malloc(sizeof(struct bstNode));
        insert(bstTree, 8);
        insert(bstTree, 5);
        insert(bstTree, 98);
        insert(bstTree, 2);
        insert(bstTree, 15);
        insert(bstTree, 65);
        insert(bstTree, 15);
        printDFS(bstTree);
    }
    
    int insert(struct bstNode *head, int val) {
        //This is the problem statement, it contains random data when I debug as it's uninitialized
        if (head->val == NULL) {
            head->val = val;
            return 0;
        }
    
        if (val < head->val) {
            if (head->left != NULL) {
                return insert(head->left, val);
            } else {
                head->left = malloc(sizeof(struct bstNode));
                head->left->val = val;
                return 0;
            }
        } else {
            if (head->right != NULL) {
                return insert(head->right, val);
            } else {
                head->right = malloc(sizeof(struct bstNode));
                head->right->val = val;
                return 0;
            }
        }
    }
    
    void printDFS(struct bstNode *head) {
        if (head->left != NULL) printDFS(head->left);
        printf("%d ", head->val);
        if (head->right != NULL) printDFS(head->right);
    }
    

2 个答案:

答案 0 :(得分:4)

教程不正确。它做了两个无效的假设。

  1. 它假设NULL等于0.虽然在大多数情况下它定义为(void *)0,但它不一定总是如此。它还使用了一个指向int的指针,因此它依赖于指针的表示。
  2. 假设初始节点在val中为0。当内存分配有malloc时,内存未初始化(因为您已经发现)。
  3. 此代码的功能还在于假设0不是要插入列表的有效值,因为它使用0作为sentinel值来表示空列表。

    假设0被用作哨兵,代码可以修复如下。

    首先,在创建初始节点时,请使用calloc而不是malloccalloc函数会将所有字节初始化为0.这将为您提供一个初始成员,val设置为0,leftright都设置为NULL

    此外,您应始终检查malloccallocrealloc的返回值,以防它们失败。

    int main() {
        struct bstNode *bstTree = calloc(1, sizeof(struct bstNode));
        if (bstTree == NULL) {
            perror("calloc failed");
            exit(1);
        }
    

    其次,通过将NULL替换为0来消除整数/指针比较。

        if (head->val == 0) {
    

    做这两件事应该让代码正常工作。

    退一步看大局,这里有一些设计问题。

    insert函数返回int,但从不使用返回值。实际上,此函数只能返回0.最好将返回类型更改为void

    让空树包含带有sentinel值的单个节点会限制您可以放入的值。最好通过将头节点作为NULL指针来获得空树。这可以通过传入头指针的地址在插入函数中解决,以便在列表为空时可以修改它:

    void insert(struct bstNode **head, int val) {
        if (*head == NULL) {
            *head = malloc(sizeof(struct bstNode));
            if (*head == NULL) {
                perror("malloc failed");
                exit(1);
            }
            (*head)->val = val;
            (*head)->left = NULL;
            (*head)->right = NULL;
            return;
        }
    
        if (val < (*head)->val) {
        ...
    

    然后你这样称呼它:

    struct bstNode *bstTree = NULL;
    insert(&bstTree, 8);
    ...
    

答案 1 :(得分:-1)

if (head->val == NULL) {
    head->val = val;
    return 0;
}

我认为tuto想要检查val是否为NULL,因为insert返回一个int。您应该通过以下方式替换插入函数:

struct bstNode *new_bstNode(int val, struct bstNode *left, struct bstNode *right)
{
    struct bstNode *elem = malloc(sizeof(*elem));
    if (elem == NULL)
        return NULL;
    elem->val = val;
    elem->left = left;
    elem->right = right;
    return elem;
}

struct bstNode *insert(struct bstNode *head, int val) {
    if (head == NULL)
        return new_bstNode(val, NULL, NULL);

    if (val < head->val) {
        if (head->left != NULL)
            return insert(head->left, val);
        else
            return head->left = new_bstNode(val, NULL, NULL);
    } else {
        if (head->right != NULL)
            return insert(head->right, val);
        else
            return head->right = new_bstNode(val, NULL, NULL);
    }
}

所以你需要替换

int main() {
    struct bstNode *bstTree = insert(bstTree, 8);
    insert(bstTree, 5);
    insert(bstTree, 98);
    insert(bstTree, 2);
    insert(bstTree, 15);
    insert(bstTree, 65);
    insert(bstTree, 15);
    printDFS(bstTree);
}