2010-03-23 66 views
1

此代碼使用基於其深度的值填充樹。但是當遍歷樹時,我無法設法確定實際的孩子數量而沒有迭代父節點。這是必要的,因爲子樓層存儲在當前節點下方的節點中。爲了將葉子直接存儲在當前節點中,需要進行哪些概念更改?在分層樹中構造葉子

#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); 
} 
+1

目前尚不清楚你想要達到的目標。請詳細說明並提供示例 – 2010-03-23 19:39:22

+0

對不起,我認爲這很清楚我的意思。那麼,問題是,在handleNode()中,我無法弄清楚當前葉的(父)節點的數量。 node-> parent-> cnt對我來說似乎很明顯,但即使添加if(node-> parent!= NULL),Valgrind也給了我很多警告,而printf()也打印了錯誤的數字。這可能是因爲在realloc()之後,指針不再顯示給同一個節點,正如Giuseppe指出的那樣。 – user206268 2010-03-23 22:56:42

+0

您不應該以這種方式使用「this」或重新定義「NULL」......如果您決定將它與C++編譯器一起使用,它可能會破壞事物。 – 2010-03-24 09:17:35

回答

1

我看到兩個問題在你的程序

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); 

可能還有其他的問題,但我強烈建議先糾正這些問題。 我希望它可以幫助你 問候

+0

1)哦,好的。我沒有想到這一點。現在我明白了Valgrind指出realloc()的原因。令人難以置信的是,我花了很多時間在錯誤的地方尋找錯誤。 2)對不起,在真正的代碼中,我沒有使用字符串,但結構,所以這不是真正的罪魁禍首。 無論如何,我之所以沒有首先使用指針數組,是因爲我害怕它們比一直在調整大小的大塊更沒有效率。 – user206268 2010-03-23 22:51:09

1

如果你的結構是一個真正的樹,然後遞歸計算節點可以幫助下面的僞代碼:

 
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 

如果在所有可能讓你使用C++,那麼我會強烈建議它。能夠使用std :: vector或std :: list來存儲您的子節點並且能夠使數據元素具有模板類型將大大簡化代碼的複雜性。

+0

準確。這就是我剩下的問題。它深入到深度> curdepth爲真的部分,因爲它在當前級別上添加了一個節點,然後才進入更深的級別。這也是葉子數量存儲在currentNode-> parent-> nodes [indexOfCurrentNode + 1] - > cnt中的原因。我目前的方法如何改進以符合你的「結構」? – user206268 2010-03-24 10:04:38