【问题标题】:Cleaning double linked list Trie structure in cc中清理双链表Trie结构
【发布时间】:2016-07-03 22:58:48
【问题描述】:

我想防止内存泄漏,所以我想释放 trie。 您可以在下面看到我尝试释放已使用的内存。

// to see how many words are cleaned up.
static int teller_cleanup = 0;

struct ac {
    int value;
    char character; 
    char * word;
    struct ac *next;
    struct ac *previous;
    struct ac *child;
    struct ac *parent;
};

它是一个双路或四路链表,不确定我应该调用它。

void cleaner(struct ac* a) {
    ac * temp = NULL;
    if (a != NULL) {
        if (a -> child == NULL && a -> next == NULL) {
            teller_cleanup ++;
            if (a -> parent != NULL) {
                temp = a -> parent;
            }
            else {
                temp = a -> previous;
             }
             free(a -> word);
             free(a);
             a = temp;
        }
        if (a -> child != NULL) {
            cleaner(a -> child);
        }
        if (a -> next != NULL) {
            cleaner(a -> next);
        }
     }
 }

int cleanup(struct ac* a) {
    // means that it is in the root
    // therfore it needs to go to the first node.
    if (a -> next == NULL && a -> parent == NULL) {
        a = a -> child;
    }
    cleaner(a);
    return teller_cleanup;
}

但它似乎无法正常工作。它给出了一个错误:

双重释放或损坏(fasttop):0x0000000000fffa70 ***

我似乎没有得到什么,因为当'child'和'next'都是'NULL'时,'a'是最外面的节点。而且我相信只有一个递归 if 语句可以到达这些最外面的节点之一。

我将尝试将特里树形象化:

[root]
   |
  \/
[h] -- > [b]
 |        |
\/       \/
[i]      [y] --> [e] 

所以 trie 包含单词 hi、by 和 be。 root 指向第一个单词的第一个字符,所有的箭头都是双链接的。从 'h' 到 'b' 是下一个,从 'h' 到 'i' 是孩子。

有人可以看到我做错了什么吗?将不胜感激。

【问题讨论】:

  • 您应该只释放父元素一次,自上而下或自下而上,而不是两种方式 - 如果您使用调试器单步执行您的代码,您会注意到 a = a->parent; [...] if(a->next != NULL) ... 之后已删除的子元素
  • 请注意,点 . 和箭头 -> 运算符绑定得非常紧密,在传统的 C 编码样式中,不应在它们周围有空格。

标签: c trie


【解决方案1】:

我认为您在多个地方检查 NULL 会使事情变得过于复杂。当你有多次递归时,在进入函数之后检查NULL比在调用它之前更容易。

此外,如果通过指向cleaner() 的指针传递局部变量,则可以避免全局变量teller_cleanup

void cleaner(struct ac *a, int *teller_cleanup) 
{
    if (a != NULL) {
        cleaner(a->next, teller_cleanup);
        cleaner(a->child, teller_cleanup);
        free(a->word);
        free(a);
        (*teller_cleanup)++;
    }
}

int cleanup(struct ac *a)
{
    int teller_cleanup = 0;
    cleaner(a, &teller_cleanup);
    return teller_cleanup;
}

【讨论】:

  • 嗯,它比我的实现做得更好,但由于某种原因,我仍然有内存泄漏。谢谢你的teller_cleanup,我没想到。
猜你喜欢
  • 2012-05-20
  • 2014-04-23
  • 1970-01-01
  • 2019-05-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多