C中的二叉树

时间:2009-02-24 05:00:17

标签: c binary-tree

我正在尝试按顺序将节点插入树中。我的功能很好......当只有三个节点时。

我有这段代码:

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。经过调试和一些研究后,我不太确定从哪里开始......

如果有人可以提供帮助,我真的很感激。

9 个答案:

答案 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

}

这与插入新树节点时一样干净。传递要插入的节点的根和值,剩下的就完成了。