C 在层次树中构造叶子

C 在层次树中构造叶子,c,hierarchical-trees,traversal,C,Hierarchical Trees,Traversal,此代码使用基于深度的值填充树。但是在遍历树时,如果不遍历父节点,我无法确定子节点的实际数量。这是必要的,因为子AFs存储在当前节点下的节点中。在当前节点中直接存储叶需要哪些概念更改 #include <string.h> #include <stdio.h> #include <stdlib.h> #ifndef NULL #define NULL ((void *) 0) #endif // ---- typedef struct _Tree_Node

此代码使用基于深度的值填充树。但是在遍历树时,如果不遍历父节点,我无法确定子节点的实际数量。这是必要的,因为子AFs存储在当前节点下的节点中。在当前节点中直接存储叶需要哪些概念更改

#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#ifndef NULL
#define NULL ((void *) 0)
#endif

// ----

typedef struct _Tree_Node {
    // data ptr
    void *p;

    // number of nodes
    int cnt;
    struct _Tree_Node **nodes;

    // parent nodes
    struct _Tree_Node *parent;
} Tree_Node;

typedef struct {
    Tree_Node root;
} Tree;

void Tree_Init(Tree *this) {
    this->root.p = NULL;
    this->root.cnt = 0;
    this->root.nodes = NULL;
    this->root.parent = NULL;
}

Tree_Node* Tree_AddNode(Tree_Node *node) {
    if (node->cnt == 0) {
        node->nodes = malloc(sizeof(Tree_Node *));
    } else {
        node->nodes = realloc(
            node->nodes,
            (node->cnt + 1) * sizeof(Tree_Node *)
        );
    }

    Tree_Node *res
        = node->nodes[node->cnt]
        = malloc(sizeof(Tree_Node));

    res->p = NULL;
    res->cnt = 0;
    res->nodes = NULL;
    res->parent = node;

    node->cnt++;

    return res;
}

// ----

void handleNode(Tree_Node *node, int depth) {
    int j = depth;

    printf("\n");

    while (j--) {
        printf("    ");
    }

    printf("depth=%d ", depth);

    if (node->p == NULL) {
        goto out;
    }

    int cnt = 0;
    for (int i = 0; i < node->parent->cnt - 1; i++) {
        if (node->parent->nodes[i] == node) {
            cnt = node->parent->nodes[i + 1]->cnt;
        }
    }

    printf("value=%s cnt=%i", node->p, cnt);

out:
    for (int i = 0; i < node->cnt; i++) {
        handleNode(node->nodes[i], depth + 1);
    }
}

Tree tree;

int curdepth;
Tree_Node *curnode;

void add(int depth, char *s) {
    printf("%s: depth (%d) > curdepth (%d): %d\n", s, depth, curdepth, depth > curdepth);

    if (depth > curdepth) {
        curnode = Tree_AddNode(curnode);

        Tree_Node *node = Tree_AddNode(curnode);

        node->p = malloc(strlen(s) + 1);
        memcpy(node->p, s, strlen(s) + 1);

        curdepth++;
    } else {
        while (curdepth - depth > 0) {
            if (curnode->parent == NULL) {
                printf("Illegal nesting\n");
                return;
            }

            curnode = curnode->parent;
            curdepth--;
        }

        Tree_Node *node = Tree_AddNode(curnode);

        node->p = malloc(strlen(s) + 1);
        memcpy(node->p, s, strlen(s) + 1);
    }
}

void main(void) {
    Tree_Init(&tree);

    curnode = &tree.root;
    curdepth = 0;

    add(0, "1");
    add(1, "1.1");
    add(2, "1.1.1");
    add(3, "1.1.1.1");
    add(4, "1.1.1.1.1");
    add(4, "1.1.1.1.2");
    add(4, "1.1.1.1.3");
    add(4, "1.1.1.1.4");
    add(2, "1.1.2");
    add(0, "2");

    handleNode(&tree.root, 0);
}
#包括
#包括
#包括
#ifndefnull
#定义空((void*)0)
#恩迪夫
// ----
类型定义结构树节点{
//数据ptr
void*p;
//节点数
int-cnt;
结构树节点**节点;
//父节点
结构树节点*父节点;
}树节点;
类型定义结构{
树节点根;
}树木;
void Tree_Init(Tree*this){
此->根.p=NULL;
此->root.cnt=0;
此->root.nodes=NULL;
此->root.parent=NULL;
}
树节点*树添加节点(树节点*节点){
如果(节点->cnt==0){
node->nodes=malloc(sizeof(Tree_node*));
}否则{
节点->节点=realloc(
节点->节点,
(节点->cnt+1)*大小(树节点*)
);
}
树节点*res
=节点->节点[节点->cnt]
=malloc(sizeof(Tree_节点));
res->p=NULL;
res->cnt=0;
res->nodes=NULL;
res->parent=节点;
节点->cnt++;
返回res;
}
// ----
void handleNode(树节点*节点,整数深度){
int j=深度;
printf(“\n”);
而(j--){
printf(“”);
}
printf(“深度=%d”,深度);
如果(节点->p==NULL){
出去;
}
int-cnt=0;
对于(inti=0;iparent->cnt-1;i++){
如果(节点->父节点->节点[i]==节点){
cnt=节点->父节点->节点[i+1]->cnt;
}
}
printf(“值=%s cnt=%i”,节点->p,cnt);
输出:
对于(int i=0;icnt;i++){
handleNode(节点->节点[i],深度+1);
}
}
树木;
int-curdepth;
树节点*curnode;
void add(整数深度,字符*s){
printf(“%s:depth(%d)>curdepth(%d):%d\n”,s,depth,curdepth,depth>curdepth);
如果(深度>电流深度){
curnode=Tree\u AddNode(curnode);
Tree\u Node*Node=Tree\u AddNode(curnode);
节点->p=malloc(strlen+1);
memcpy(节点->p,s,strlen(s)+1);
curdepth++;
}否则{
而(curdepth-深度>0){
如果(curnode->parent==NULL){
printf(“非法嵌套”);
返回;
}
curnode=curnode->parent;
凝乳深度--;
}
Tree\u Node*Node=Tree\u AddNode(curnode);
节点->p=malloc(strlen+1);
memcpy(节点->p,s,strlen(s)+1);
}
}
真空总管(真空){
Tree_Init(&Tree);
curnode=&tree.root;
curdepth=0;
添加(0,“1”);
添加(1,“1.1”);
添加(2,“1.1.1”);
添加(3,“1.1.1.1”);
增加(4,“1.1.1.1.1”);
增加(4,“1.1.1.1.2”);
增加(4,“1.1.1.1.3”);
增加(4,“1.1.1.1.4”);
添加(2,“1.1.2”);
添加(0,“2”);
handleNode(&tree.root,0);
}

我发现您的程序中有两个问题

1) 当您“realloc”节点列表时,实际上是在内存中移动节点对象,因此其子节点中的父指针也必须更新。我建议您将节点数组转换为指向节点的指针数组,这样您就可以在不更正指针的情况下重新定位它

2) 您忘记终止字符串:

  node->p = malloc(strlen(s));
  memcpy(node->p, s, strlen(s));
应该是:

  node->p = malloc(strlen(s)+1);
  memcpy(node->p, s, strlen(s)+1);
或者干脆

  node->p = strdup(s);
也许还有其他问题,但我强烈建议先纠正这些问题。 我希望它能帮助你
关于

如果您的结构确实是一棵树,那么以下递归计算节点的伪代码可能会有所帮助:

def total_number_of_leaf_nodes(node): if node does not have children: return 1 else: sum = 0 for each child of node: sum += total_number_of_leaf_nodes(child) return sum def叶节点总数(节点): 如果节点没有子节点: 返回1 其他: 总和=0 对于节点的每个子节点: 总和+=叶节点(子节点)的总数 回报金额
<>如果你完全可以使用C++,那么我会强烈建议它。能够使用std::vector或std::list来存储子节点,并且能够使数据元素具有模板类型,这将大大简化代码的复杂性

现在还不清楚你想要实现什么。请详细说明并提供一个例子对不起,我想我的意思很清楚。问题是,在handleNode()中,我无法计算当前叶的(父)节点数。node->parent->cnt对我来说似乎很明显,但即使在添加了if(node->parent!=NULL)之后,Valgrind也给了我很多警告,printf()也打印了错误的数字。这可能是因为在realloc()之后,指针不再像Giuseppe指出的那样显示在同一个节点上。您不应该以那种方式使用“this”或重新定义“NULL”。。。它可以打破事情,如果你决定使用它与一个C++编译器。项目绑定到C,所以它不应该是一个问题。默认情况下未定义NULL。甚至有些glibc类也会(重新)定义NULL。@timn,如果重新定义NULL,应该将其定义为0或0L,而不是((void*)0,因为这样做是不兼容的定义。1)哦,好的。我没想到。现在我明白了为什么Valgrind指向realloc()。难以置信,我花了这么多时间在错误的地方寻找那个虫子。2) 抱歉,在实际代码中,我没有使用字符串,而是使用结构,所以这不是真正的罪魁祸首。不管怎么说,我之所以不使用指针数组,首先是因为我担心它们比一直调整大数据块的大小效率更低。这就是我剩下的问题。这取决于深度>curdepth为真的部分,因为它在当前级别上添加了一个节点,然后才进入更深的级别。这也是为什么叶子的数量存储在currentNode->parent->nodes[indexOfCurrentNode+1]->cnt中的原因。如何改进我当前的方法以匹配您的“结构”?