我有一个n-ary树结构,就像答案here中解释的那样:
typedef struct node {
int ID;
struct node *child; // points to (first) child
struct node *next; // points to next node at same level (sibling)
struct node *parent; // points to parent
} node;
使用malloc
创建节点。
我想编写一个函数,将树的根更改为另一个(指定的)节点,并释放所有节点的内存 - 由于根的更改 - 不再是树的一部分(即如果某个节点无法通过父节点追溯到新根节点,则应将其设置为NULL
并释放其内存。
例如,如果这是我的树:
1
/ \
2 3
/ \ \
4 5 6
/ \
7 8
我希望将根目录从1更改为3,然后在调用prune_tree函数后,root将为3,并且除了3和6之外的每个节点的内存都将被释放。
我最接近解决问题涉及此功能:
void prune_tree(node **root, node *new_root) {
if (*root == NULL || (*root)->parent == new_root)
return;
prune_tree(&((*root)->child), new_root);
prune_tree(&((*root)->next), new_root);
free(*root);
*root = NULL;
}
并在调用此函数后设置
root = new_root;
我主要通过反复试验来到这里;事实上,我甚至不确定为什么在我测试它的大部分时间都能正常工作。它还添加了在调用函数后必须将根设置为新根地址的不必要步骤。我假设我可以修改函数中的根地址,或者返回新的根地址。
我认为我不需要担心内存使用,因为该函数正在释放内存,但最好是节省时间的函数。我不确定这是否意味着我应该避开递归......
答案 0 :(得分:0)
您的方法不起作用,因为您将释放新根本身。您只能在parent
是新根的节点上停止。
以下是更正后的版本:
void prune_tree(node **root, node *new_root) {
if (*root == NULL)
return;
if (*root == new_root) {
(*root)->parent = NULL;
return;
}
prune_tree(&(*root)->child, new_root);
prune_tree(&(*root)->next, new_root);
free(*root);
*root = NULL;
}
在使用地址调用此函数后,您仍需要将树的根更新为new_root
:
prune_tree(&root, new_root);
root = new_root;
答案 1 :(得分:0)
递归函数对此非常完美。
你基本上想要做什么(假设树中没有循环)是删除新根的所有兄弟,包括他们的孩子和父母以及根的父母。
算法可以是:
typedef struct node {
int ID;
struct node *child;
struct node *sibling;
struct node *parent;
} node;
void remove_node(struct node* node, struct node* root)
{
if(node->parent != NULL)
remove_node(node->parent, new_root)
if(node->sibling != NULL)
remove_node(node->sibling, new_root)
if((node->child != NULL) && (node->child != root))
remove_node(node->sibling, new_root)
free(node)
}
void prune_tree(node **root, node *new_root) {
*root = new_root
remove_node(new_root->parent);
remove_node(new_root->sibling);
}
假设:
答案 2 :(得分:0)
我想我找到了解决方案......
void prune_tree(node** root, node* new_root)
{
bool del = true;
if (*root == NULL)
return;
if (*root == new_root) {
del = false;
}
if (del){
prune_tree(&(*root)->child, new_root);
prune_tree(&(*root)->next, new_root);
free(*root);
*root = NULL;
}
else{
prune_tree(&(*root)->next, new_root);
}
}