我正在研究二叉树问题,我已经提出了以下适用于插入的实现。
int insert(Node ** n, int data) {
// create new node
if (*n == NULL) {
*n = (Node*) malloc(sizeof(Node));
(*n)->data = data;
(*n)->left = NULL;
(*n)->right = NULL;
return 1;
}
else if (data > (*n)->data) {
insert(&(*n)->right, data);
}
else {
insert(&(*n)->left, data);
}
return 0;
}
但是为了尝试简化这个功能,我尝试将* n分配给本地节点指针,如:
Node * c = *n;
然后我通过该函数并用c替换了* n的所有实例。但是,该功能无法正常执行。任何人都可以向我解释为什么这不起作用?感谢。
编辑:我应该指出,在新的更改中,函数将在第一个if语句后立即退出。这似乎表明传入的指针(根)始终为NULL,这意味着节点未正确保存。不知道原因是什么,但我认为它介于本地指针和第一个if语句的结尾之间。
EDIT2:我在第一个if块的末尾进行了以下检查:
if (*n != NULL) printf("Node has been allocated\n");
永远不会执行!
答案 0 :(得分:2)
我认为:
插入(&(* n) - >右,数据); 和 插入(& c->右,数据);
不一样。
c在内存中的位置与&(* n)不同。
答案 1 :(得分:2)
你的问题是你把'c'变成了一个局部变量,并编辑了它的内容,但你需要编辑非局部变量。
如果在每次返回之前执行*n = c;
(或修改代码,因此只有一次返回,并在此之前进行重新分配),则可能没问题。所以 - 未经验证的代码:
int insert(Node ** n, int data) {
Node *c = *n;
int rc = 0;
// create new node
if (c == NULL) {
c = (Node*) malloc(sizeof(Node));
c->data = data;
c->left = NULL;
c->right = NULL;
rc = 1;
}
else if (data > c->data) {
rc = insert(&c->right, data);
}
else {
rc = insert(&c->left, data);
}
*n = c;
return rc;
}
使用测试工具。印刷并不华丽 - 但它至少有效。请注意,您需要使用后订单遍历来释放树;打印可以预先订购,也可以按顺序(如此处)或订购后完成。
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
typedef struct Node Node;
struct Node
{
int data;
Node *left;
Node *right;
};
static void insert(Node **n, int data)
{
Node *c = *n;
if (c == NULL)
{
// create new node
c = (Node*) malloc(sizeof(Node));
c->data = data;
c->left = NULL;
c->right = NULL;
}
else if (data > c->data)
insert(&c->right, data);
else
insert(&c->left, data);
*n = c;
}
static void dumptree(Node **tree, const char *tag)
{
assert(tree != 0);
Node *node = *tree;
if (node != 0)
{
dumptree(&node->left, "left");
printf("data: %d (%s)\n", node->data, tag);
dumptree(&node->right, "right");
}
}
static void dump(Node **tree, const char *tag)
{
printf("In-Order Dump (%s)\n", tag);
dumptree(tree, "root");
}
static void freetree(Node **tree)
{
assert(tree != 0);
Node *node = *tree;
if (node != 0)
{
freetree(&node->left);
freetree(&node->right);
free(node);
//*tree = 0;
}
}
int main(void)
{
Node *base = 0;
int array[] = { 3, 9, 1, 4, 8, 2, 5, 7, 0, 6 };
int i;
for (i = 0; i < 10; i++)
{
char buffer[32];
sprintf(buffer, "Add node %d", array[i]);
insert(&base, array[i]);
dump(&base, buffer);
}
freetree(&base);
return 0;
}
答案 2 :(得分:0)
insert(&(*n)->right, data);
应该是:
insert((*n)->right, data);
在insert() - 调用中, (*n)
而不是&(*n)
。这是因为* n是你的节点指针,你不需要(也不能)取* n的地址。如果这不起作用,请发布您的完整代码incl。节点结构。
答案 3 :(得分:0)
我真的没有得到一个树的双指针。 这是另一个建议:
#include <stdlib.h>
#include <stdio.h>
struct tree; //forward declaration
struct tree {
int data;
struct tree * right;
struct tree * left;
};
typedef struct tree Node;
Node* insert(Node * n, int data) {
// create new node
if (n == NULL) { //We are at the first node
//It is of no use to create a malloc on n since the value will not be updated in the previous calling function since n is NULL. So we would have to return it
Node * n = (Node*) malloc(sizeof(Node));
n->data = data;
n->left = NULL;
n->right = NULL;
return n;
} else {
//n is not NULL
if (data > n->data) {
if(n->right != NULL) {
//We have to do recursion
insert(n->right, data); // n->right is a pointer, type Node*
} else {
//We don't want to send a NULL in the recursive call, cause it wouldn't update
n->right = (Node*) malloc(sizeof(Node));
n->right->data = data;
n->right->right = NULL;
n->right->left = NULL;
}
} else {
if(n->left != NULL) {
//We have to do recursion
insert(n->left, data); // n->right is a pointer, type Node*
} else {
//We don't want to send a NULL in the recursive call, cause it wouldn't update
n->left = (Node*) malloc(sizeof(Node));
n->left->data = data;
n->left->right = NULL;
n->left->left = NULL;
}
}
return NULL;
}
}
int main(void) {
Node * root = NULL;
root = insert(root, 10); //First call to initialise the root
insert(root, 11);
printf("%d \n", root->data);
return 0;
}
到目前为止,我的电脑似乎运行良好。 它会满足您的需求吗?
如果您需要精确的话,请随意。