【问题标题】:how to create a n-ary tree in c如何在c中创建n叉树
【发布时间】:2015-05-21 06:15:33
【问题描述】:
#include <stdio.h>
#include <stdlib.h>


struct node{
  char *word;
  int depth, children;
  struct node  **child;
};

typedef struct node node;


node *createTree();
node *createNode(char *word,int depth);

int main(int argv,char *argc[]){
   node *root,*current_node;
   root=createNode("root",0);
   char *array[]={"string1","string2","string3"};
   current_node=root;
   printf("root has been created with word: %s \n",current_node->word);
   int i;
   for (i=0; i<3; i++){
      current_node->child[i]=createNode(array[i],(current_node->depth)+1);
      current_node->children++;
      printf("%s  has been inserted to the tree\n",current_node->word);
   }

}



node *createTree(){
   printf("root has been created\n");
   return createNode("",0);    /*creates the first node*/
}

node *createNode(char *word,int depth){
   node *new_node;
   new_node=malloc(sizeof(node));
   new_node->word=word;
   new_node->depth=depth;
   new_node->children=0;
   new_node->child=NULL;
}

所以我在这里要做的是构建一个 n 叉树。我使用 createNode 函数来创建根的子节点,但是一旦我尝试将新节点的地址链接到子节点,程序就会因分段错误而崩溃。我知道我的错误可能是,我试图创造孩子的方式,但我找不到。帮助任何人?

【问题讨论】:

  • 创建节点时,child 指针被设置为NULL。但是您的for 循环试图引用child[i],所以这是一个分段错误。您需要为child 节点指针数组分配内存,然后才能引用它们。

标签: c struct tree


【解决方案1】:

在使用之前为child结构成员分配内存:

current_node->child = malloc(3 * sizeof(node *));

for (i=0; i<3; i++) {
    current_node->child[i] = createNode(array[i],(current_node->depth)+1);
    current_node->children++;
    printf("%s  has been inserted to the tree\n",current_node->word);
}

您定义的结构意味着您必须将每个级别作为具有潜在动态元素数量的节点数组来管理。用于 C 中的 n 叉树表示的更常见的结构是:

struct node {
    char *word;
    int depth, children;  // Reconsider if you need these
                          //   for maintenance effort versus benefit
    struct node *child;   // point to children of this node
    struct node *next;    // point to next node at same level
};

所以结构看起来像这样:

Root -> NULL
 |
 V
Child-1.1 -> Child-1.2 -> ... -> Child-1.n -> NULL
 |              |                   |            
 |              V                   V
 |              ...              Child-1.n.1 -> ... -> NULL
 V
Child-1.1.1 -> Child-1.1.2 -> ... -> NULL
 |
 ... etc

然后您需要修改您的createNode 并相应地编写您的其他树管理例程。它们可能看起来如何的部分且非常简洁的示例(不一定包含所有正确的有效性检查或节点移除/释放):

struct node {
    int data;
    struct node *next;
    struct node *child;
};

typedef struct node node;

node * new_node(int);
node * add_sibling(node *, int);
node * add_child(node *, int);

int main(int argc, char *argv[])
{
    int i;
    node *root = new_node(0);

    for ( i = 1; i <= 3; i++ )
        add_child(root, i);
}

node * new_node(int data)
{
    node *new_node = malloc(sizeof(node));

    if ( new_node ) {
        new_node->next = NULL;
        new_node->child = NULL;
        new_node->data = data;
    }

    return new_node;
}

node * add_sibling(node * n, int data)
{
    if ( n == NULL )
        return NULL;

    while (n->next)
        n = n->next;

    return (n->next = new_node(data));
}

node * add_child(node * n, int data)
{
    if ( n == NULL )
        return NULL;

    if ( n->child )
        return add_sibling(n->child, data);
    else
        return (n->child = new_node(data));
}

【讨论】:

  • 非常感谢。我使用了你指出的结构。那真的很有帮助。还可以告诉我一种打印或搜索此数据结构中节点的方法吗?我对 C 语言尤其是数据结构还很陌生,而且我遇到了困难。
  • @HliasA。我想如果你稍微研究一下这个结构,你就可以弄清楚这一点。它只是基于简单的链接列表,您可以在其中跟随链接直到看到NULLadd_sibling 函数就是一个例子)。要打印整个结构,您需要决定是进行广度优先还是深度优先遍历。但这是相同的想法:只需点击链接并在每一步打印。我将把这部分留作练习。继续尝试,如果你有一个特定的实现并且卡住了,你可以发布另一个关于它的问题。
  • 非常感谢您展示了要使用的正确数据结构..
【解决方案2】:

一些可能有用的附加功能

void remove_node(node* node, node* new_root)
{
    if(node->parent != NULL)
        remove_node(node->parent, new_root)

    if(node->next != NULL)
        remove_node(node->next, new_root)

    if((node->child != NULL) && (node->child != new_root))
        remove_node(node->child, new_root)

    free(node)
}

// new root must be element of the tree
void new_root_tree(node **root, node *new_root) {
    *root = new_root
    remove_node(new_root->parent);
    remove_node(new_root->next);
}

【讨论】:

    猜你喜欢
    • 2021-03-10
    • 1970-01-01
    • 2010-09-16
    • 1970-01-01
    • 1970-01-01
    • 2015-02-08
    • 1970-01-01
    • 2010-10-24
    • 1970-01-01
    相关资源
    最近更新 更多