如何有效地释放这棵树?该算法应适用于此类树中的任何给定节点。所以我将指向节点,该节点将是“根”节点。我想释放该节点下面的所有内容。
树中的每个节点都是这个结构:
typedef struct tag
{
struct tag* parent;
struct tag* nextSibling;
struct tag* previousSibling;
struct tag* firstChild;
struct tag* lastChild;
char* name;
char* text;
}node;
答案 0 :(得分:1)
使用任何标准树遍历机制并删除所有元素。
答案 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分配树节点,所有节点都来自同一个池,并且池中不包含其他树的节点,则可以立即释放整个内存池,使您不必遍历整个树。这样会更有效率,因为它可以避免潜在大型树中的大量缓存未命中,并且还可以避免某些内存碎片问题。