如何有效地释放树

时间:2013-03-28 16:58:27

标签: c tree free

如何有效地释放这棵树?该算法应适用于此类树中的任何给定节点。所以我将指向节点,该节点将是“根”节点。我想释放该节点下面的所有内容。 enter image description here

树中的每个节点都是这个结构:

  typedef struct tag
  {
      struct tag* parent;
      struct tag* nextSibling;
      struct tag* previousSibling;
      struct tag* firstChild;
      struct tag* lastChild;     
      char* name;
      char* text;     
  }node;

3 个答案:

答案 0 :(得分:1)

使用任何标准树遍历机制并删除所有元素。

http://en.wikipedia.org/wiki/Tree_traversal

答案 1 :(得分:1)

我想这会奏效。但实际上,Dariusz是正确的。您只需使用有效的树遍历,并在每个节点上执行操作。

问题已更改: 由于您希望此操作在树中的任何节点上运行,因此请先找到根目录。编写一个在一个方向上进行的树遍历比在树上下进行更容易。

您已将问题从删除树更改为删除树的子集。所以,相反,让我们这样做。首先从树中删除元素(remove_node)。然后执行与之前相同的免费工作。

void remove_node(node *self) {
    if (self->previousSibling)
        self->previousSibling->nextSibling = self->nextSibling;
    if (self->nextSibling)
        self->nextSibling->previousSibling = self->previousSibling;
    if (self->parent && self->parent->firstChild == self)
        self->parent->firstChild = self->nextSibling;
    if (self->parent && self->parent->lastChild == self)
        self->parent->lastChild = self->previousSibling;
}

void free_node(node *self) {
    // Free one node. Perhaps this is:
    free(self->name);
    free(self->text);
    free(self);
}

void iterate_nodes(node *root, void op(node *self) ) {
    if (root == NULL)
        return;
    iterate_nodes(root->nextSibling, op);
    iterate_nodes(root->firstChild, op);
    op(root);
}

int main() {
    node *node = NULL; // Some node in the tree...
    remove_node(node);
    iterate_nodes(node, free_node);
}

答案 2 :(得分:0)

您可以使用标准的后序树遍历算法来释放整个树。要使它在任何给定节点上工作,只需遍历到根的所有父链接即可。例如:

void free_tree(node *n)
{
    // Find the root node of the tree
    while(n->parent)
        n = n->parent;

    free_tree_helper(n);
}

void free_tree_helper(node *n)
{
    // Free all children of this node in post-order traversal
    node *child = n->firstChild;
    while(child)
    {
        // Save the next sibling pointer to avoid dangling pointers
        node *next = child->nextSibling;
        free_tree_helper(child);
        child = next;
    }

    // All the children have been freed, now free the parent
    free(n->name);
    free(n->text);
    free(n);
}

或者,如果使用memory pool分配树节点,所有节点都来自同一个池,并且池中不包含其他树的节点,则可以立即释放整个内存池,使您不必遍历整个树。这样会更有效率,因为它可以避免潜在大型树中的大量缓存未命中,并且还可以避免某些内存碎片问题。