我正在查看本教程http://www.learn-c.org/en/Binary_trees,并在insert函数中将int与NULL进行比较。它似乎在tut网站上运行良好,但它对我不起作用,我的研究告诉我它应该不起作用。我的代码如下。
如果教程错误,有没有办法动态设置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);
}
答案 0 :(得分:4)
教程不正确。它做了两个无效的假设。
NULL
等于0.虽然在大多数情况下它定义为(void *)0
,但它不一定总是如此。它还使用了一个指向int
的指针,因此它依赖于指针的表示。val
中为0。当内存分配有malloc
时,内存未初始化(因为您已经发现)。此代码的功能还在于假设0不是要插入列表的有效值,因为它使用0作为sentinel值来表示空列表。
假设0被用作哨兵,代码可以修复如下。
首先,在创建初始节点时,请使用calloc
而不是malloc
。 calloc
函数会将所有字节初始化为0.这将为您提供一个初始成员,val
设置为0,left
和right
都设置为NULL
此外,您应始终检查malloc
,calloc
和realloc
的返回值,以防它们失败。
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);
}