在C中释放二进制树结构

时间:2015-09-23 07:19:30

标签: c algorithm tree binary-tree

我有一个链表,我猜一棵树看起来像这样:  enter image description here

-> grandma
    -> dad
        -> me
        -> sister
            -> niece
        -> brother
    -> uncle
        -> cousin

我有一个结构如下

struct Node{
    Node *parent;
    Node *next;
    Node *child;
}

我如何释放该链表? 我的想法是先进行深度搜索并取消分配每个节点吗?

4 个答案:

答案 0 :(得分:4)

递归深度搜索(DFS):你是对的,这是处理二进制树内存的好方法:

remove(node):
    if node is null: return

    //else
    remove(left node)
    remove(right node)

    free(node)

迭代解决方案https://codegolf.stackexchange.com/questions/478/free-a-binary-tree
由于您不想使用任何递归解决方案,因此您可以找到描述良好的迭代解决方案。

答案 1 :(得分:2)

您可以优化树的分配/取消分配。

想象一下,你想创建20或30人的树。您可以分配30个Node结构的数组:

size_t currentArraySize = 30;
Node* nodes = (Node*)malloc(currentArraySize * sizeof(Node));
size_t nextFreeIndex = 0;

要添加新元素,您可以编写简单的函数:

Node* allocateNode()
{
    // Oops! There's not more memory in the buffer.
    // Lets increase its size.
    if (nextFreeIndex >= currentArraySize) {
        currentArraySize *= 2;
        Node* newNodes = (Node*)realloc(nodes, currentArraySize * sizeof(Node));

        // Should correct pointers (thanks to user3386109)
        if (newNodes != nodes) {
            for (size_t i = 0; i < nextFreeIndex; i++) {
                if (newNodes[i]->parent != NULL)
                    newNodes[i]->parent -= nodes += newNodes;
                if (newNodes[i]->next != NULL)
                    newNodes[i]->next -= nodes += newNodes;
                if (newNodes[i]->child != NULL)
                    newNodes[i]->child -= nodes += newNodes;
            }
        }
    }

    return nodes[nextFreeIndex++];
}

要解除分配所有节点,您只需free单个指针nodes

现在代码看起来有些可怕,因为写了user3386109,所以我们可以稍微简化一下:

Node* allocateNode()
{
    // Oops! There's not more memory in the buffer.
    // Lets increase its size.
    if (nextFreeIndex >= currentArraySize) {
        currentArraySize *= 2;
        Node* newNodes = (Node*)realloc(nodes, currentArraySize * sizeof(Node));

        // Should correct pointers (thanks to user3386109)
        if (newNodes != nodes)
            correctPointers(newNodes, nodes);
    }

    return nodes[nextFreeIndex++];
}

#define correctPointer(pointer, oldOffset, newOffset) if (pointer != NULL) { \\
                                                          pointer -= oldOffset; \\
                                                          pointer += newOffset; \\
                                                      }

void correctPointers(Node* newNodes, Node* nodes)
{
    for (size_t i = 0; i < nextFreeIndex; i++) {
        correntPointer(newNodes[i]->parent, nodes, newNodes);
        correntPointer(newNodes[i]->child, nodes, newNodes);
        correntPointer(newNodes[i]->next, nodes, newNodes);
    }
}

答案 2 :(得分:1)

迭代版,灵感来自Day-Stout-Warren算法:

void removetree(Node *node)
{
    while(node != NULL)
    {
        Node *temp = node;

        if(node->child != NULL)
        {
            node = node->child;
            temp->child = node->next;
            node->next = temp;
        }
        else
        {
            node = node->next;
            remove(temp);
        }
    }
}

这个算法有点像尝试将树转换为与next指针单链接的列表,这很容易通过迭代取消链接和销毁第一个项目来销毁。但是它永远不会完成转换,因为它尽可能地取消链接并删除头节点,尽管其余的树尚未转换。也就是说,它将 relink 步骤与 unlink-and-destroy 步骤交错。

我们使用if指令测试第一个(头部)节点是否有子节点。如果是这样,我们将其子项设为新头,当前节点成为新头next节点。这样,我们在第一级列表中还有一个next链接。 now-head节点的“下一个”成为前一个节点的子节点,现在是头部的第一个next

transformation step

另一方面,如果头节点没有子节点,则可能会将其删除,并且next成为新头。

这两个步骤由while循环迭代,直到所有子节点都转换为兄弟节点并随后删除。

答案 3 :(得分:-3)

您可以使用递归解决方案

free(root)
{
    if (root->next == null)
    {
        free(node)
    }
    free(root->left)
    free(right->)
}