【问题标题】:How to empty a GLib Tree?如何清空 GLib 树?
【发布时间】:2018-05-14 15:57:42
【问题描述】:

为了清空 GLib 树,必须首先遍历树并填写所有找到的键的列表。然后可以使用g_tree_remove 函数清空树。问题是我不确定如何从遍历函数中填充列表。这是我尝试过的

#include <stdio.h>
#include <stdlib.h>
#include <glib.h>

//Prototypes
gint treeCompareFunction (const gchar* a, const gchar* b, gpointer self);
gboolean traverseTree(gpointer key, gpointer value, gpointer data);

int main()
{
    GTree* tree = g_tree_new_full ((GCompareDataFunc) treeCompareFunction, NULL, NULL, NULL);
    // Insert data into the tree
    g_tree_insert (tree, "key 1", "val 1");
    g_tree_insert (tree, "key 2", "val 2");
    g_tree_insert (tree, "key 3", "val 3");

    GSList* list = NULL;
    // Try to get all the keys of the tree in a list
    g_tree_foreach (tree, (GTraverseFunc)traverseTree, list);
    printf ("List size after tree traversal: %"  G_GUINT32_FORMAT "\n", g_slist_length(list));
    //TODO empty the tree
    return 0;
}

gint treeCompareFunction (const gchar* a, const gchar* b, gpointer self) {
    return g_strcmp0(a, b);
}

gboolean traverseTree(gpointer key, gpointer value, gpointer data) {
 data = g_slist_append(data, key);
 printf ("List size in traversal function: %"  G_GUINT32_FORMAT "\n", g_slist_length(data));
 return FALSE;
}

输出是

List size in traversal function: 1
List size in traversal function: 1
List size in traversal function: 1
List size after tree traversal: 0

如何获取列表中的所有键然后清空树?

【问题讨论】:

    标签: c glib


    【解决方案1】:

    你需要传递一个指向你的GSList*的指针,而不是GSList*本身,否则遍历函数正在修改一个指向列表头的本地指针,而不是@987654323中指向列表头的指针@。

    GSList *list = NULL;
    g_tree_foreach (tree, (GTraverseFunc)traverseTree, &list);
    …
    
    gboolean traverseTree(gpointer key, gpointer value, gpointer data) {
     GSList *out_list = data;
     *out_list = g_slist_append(*out_list, key);
     printf ("List size in traversal function: %"  G_GUINT32_FORMAT "\n", g_slist_length(*out_list));
     return FALSE;
    }
    

    另外,请注意,使用 g_slist_append() 迭代地附加到链表会给你 O(N^2) 的性能,而 g_slist_length() 需要 O(N) 时间。总体而言,使用指针数组会更容易、更高效:

    GPtrArray *items_to_remove = g_ptr_array_sized_new (g_tree_nnodes (tree));
    g_tree_foreach (tree, (GTraverseFunc)traverseTree, items_to_remove);
    …
    
    gboolean traverseTree(gpointer key, gpointer value, gpointer data) {
     GPtrArray *items_to_remove = data;
     g_ptr_array_add(items_to_remove, key);
     printf ("List size in traversal function: %u\n", items_to_remove->len);
     return FALSE;
    }
    

    【讨论】:

    • 谢谢。它就是这样工作的。我编辑了问题代码,因为在应用解决方案时,我意识到树的销毁通知函数两次释放内存并导致无效指针错误。现在我的代码与这个应用的答案按预期工作。
    猜你喜欢
    • 2021-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-21
    • 2012-04-05
    • 1970-01-01
    • 2011-07-08
    • 1970-01-01
    相关资源
    最近更新 更多