我正在尝试按顺序将节点插入树中。我的功能很好......当只有三个节点时。
我有这段代码:
typedef struct _Tnode Tnode;
struct _Tnode {
char* data;
Tnode* left;
Tnode* right;
};
同时:
Tnode* add_tnode(Tnode* current_node, char* value) {
Tnode* ret_value;
if(current_node == NULL) {
current_node = (Tnode*) malloc(sizeof(Tnode));
if(current_node != NULL) {
(current_node)->data = value;
(current_node)->left = NULL;
(current_node)->right = NULL;
ret_value = current_node; }
else
printf("no memory");
}
else {
if(strcmp(current_node->data,value)) { //left for less than
ret_value = add_tnode((current_node->left), value);
current_node -> left = (Tnode*) malloc(sizeof(Tnode));
(current_node -> left) -> data = value;
}
else if(strcmp(current_node->data,value) > 0) {
ret_value = add_tnode((current_node -> right), value);
current_node -> right = (Tnode*) malloc(sizeof(Tnode));
(current_node -> right) -> data = value;
}
else {
printf("duplicate\n");
ret_value = current_node;
}
}
return ret_value;
}
我知道这里有什么问题,我只是不知道如何修复它。这只会覆盖连接到根节点的两个节点。即。
|root_node|
/ \
|node_2| |node_3|
我无法添加一个节点四。它只是根据输入覆盖节点2或3。经过调试和一些研究后,我不太确定从哪里开始......
如果有人可以提供帮助,我真的很感激。
答案 0 :(得分:2)
这似乎只是一个学校项目。
从哪里开始。
1)你在树下一直左右晃动。我不确定为什么你会期望它们被保留,因为: a)您总是写入这些节点。 b)返回现有节点的唯一时间是strcmp匹配。
2)你真的需要检查strcmp<第一次比较时为0。
3)对于非平衡树,没有理由使用递归 - 你可以使用一个循环,直到你到达一个叶子然后钩住叶子。如果你真的想要递归...
4)Recursive ...在所有情况下都返回NULL,除非你创建一个节点(即:你有当前的第一部分== NULL)。
5)在左/右,将返回值存储在临时本地节点*中。只有当返回值不为NULL时,才应指定左/右。
即使这对我来说也不合适,但如果我从零开始,它根本就不会像这样。 :)我们甚至不会进入内存泄漏/崩溃,你可能最终只会在所有威利不知名的情况下推送'char *'值。
答案 1 :(得分:2)
您应该将mallocing仅保留到插入到达叶节点的情况(即NULL)。在其他情况下,您应该做的就是根据您的比较遍历到下一个级别。在你的情况下,你正在遍历下一个级别,然后用一个新的malloc杀死它。因此,你永远不会超越第一级。
例如
if (current_node == NULL) // Do initialization stuff and return current_node
if (strcmp(current_node->data, value) < 0) {
current_node->left = add_tnode((current_node->left), value);
} else if (strcmp(current_node->data, value) > 0) {
current_node->right = add_tnode((current_node->right), value);
}
return current_node;
答案 2 :(得分:2)
struct _Tnode {
char* data;
struct _Tnode * left, * right;
};
typedef struct _Tnode Tnode;
void addNode(Tnode ** tree, Tnode * node){
if(!(*tree)){
*tree = node;
return;
}
if(node->data < (*tree)->val){
insert(&(*tree)->left, node);
}else if(node->data>(*tree)->data){
insert(&(*tree)->right, node);
}
}
答案 3 :(得分:1)
对于初学者 - 第一个strcmp
if(strcmp(current_node-&gt; data,value))
可能不对 - 这对于小于和大于都是如此,然后第二个如果没有意义
答案 4 :(得分:0)
我猜你需要在_Tnode
结构的父节点上添加一个指针。
答案 5 :(得分:0)
问题是,在你的递归函数调用add_tnode后,在左侧分支上,比如说,你正在用malloc删除相同的分支。 malloc应该只在您递归到将要添加节点的点时发生,而不是在您进行递归调用时。
本质上,在一个特定的函数调用中,你应该进行递归调用或malloc一个新节点,而不是两者。
这也可能产生内存泄漏。
答案 6 :(得分:0)
一旦你发现,current_node-&gt;数据不为空并将其与值进行比较,首先必须检查相应的指针current_node-&gt; left(或 - &gt; right)是否已经在使用中(! = NULL)。
如果为null,则按原样继续操作。现在情况正常。
如果没有,则必须在对应节点上重新测试整个事件,在相应的节点上再次调用您的函数。这里有一些伪代码:
用以下代码包装代码:
void Add_node(Tnode* current_node) {
...
else {
if(strcmp(current_node->data,value) < 0) { //left for less than
if(current_node->left != NULL) {
Add_node(current_node->left);
} else {
ret_value = add_tnode((current_node->left), value);
current_node -> left = (Tnode*) malloc(sizeof(Tnode));
(current_node -> left) -> data = value;
} else if(strcmp(current_node->data,value) > 0) {
Add_node(current_node->right);
} else {
...
}
这称为recoursion(函数callin本身)并遍历树。要读取某个节点,您必须再次执行递归功能。小心它们终止(在某些时候,左或右指针将为null,从而终止递归调用)。
答案 7 :(得分:0)
如果您没有为自己的启发实现此功能,我只会使用libavl
答案 8 :(得分:0)
您不需要知道节点的父节点。只是当前节点的值。
伪代码:
add_treenode(root, value)
{
//check if we are at a leaf
if root == null
allocate space for new node.
set children to null
save root->value = value
return root // if you need to return something, return the node you inserted.
//if not, this node has a value
if root->value < value //use strcmp since value is a string
add_tnode(root->left, value)
else
add_tnode(root->right, value)
return NULL
}
这与插入新树节点时一样干净。传递要插入的节点的根和值,剩下的就完成了。