4_15_GLib库入门与实践_N叉树

简介

平衡二叉树是一种特殊的树,前面已经介绍过。本章介绍的是N叉树。
(本节以下内容翻译自官方文档)
GNode 结构及其相关函数提供了一个 N 叉树数据结构,其中树中的节点可以包含任意数据。
要创建一棵新树,请使用 g_node_new()。
要将节点插入树中,请使用 g_node_insert()、g_node_insert_before()、g_node_append() 和 g_node_prepend()。
要创建一个新节点并将其插入树中,请使用 g_node_insert_data()、g_node_insert_data_after()、g_node_insert_data_before()、g_node_append_data() 和 g_node_prepend_data()。
要反转节点的子节点,请使用 g_node_reverse_children()。
要查找节点,请使用 g_node_get_root()、g_node_find()、g_node_find_child()、g_node_child_index()、g_node_child_position()、g_node_first_child()、g_node_last_child()、g_node_nth_child()、g_node_first_sibling()、g_node_prev_sibling()、g_node_next_sibling() 或 g_node_last_sibling()。
要获取有关节点或树的信息,请使用 G_NODE_IS_LEAF()、G_NODE_IS_ROOT()、g_node_depth()、g_node_n_nodes()、g_node_n_children()、g_node_is_ancestor() 或 g_node_max_height()。
要遍历树,为遍历中访问的每个节点调用一个函数,使用 g_node_traverse() 或 g_node_children_foreach()。
要从树中删除节点或子树,请使用 g_node_unlink() 或 g_node_destroy()。

数据结构

树上的一个节点,各成员变量含义如下。

struct GNode {
  gpointer data; // 指向用户数据的指针
  GNode   *next; // 下一个节点
  GNode   *prev;  // 上一个节点
  GNode   *parent;  // 父节点
  GNode   *children;  // 子节点
};

函数列表

GNode * 	g_node_new ()
GNode * 	g_node_copy ()
gpointer 	(*GCopyFunc) ()
GNode * 	g_node_copy_deep ()
GNode * 	g_node_insert ()
GNode * 	g_node_insert_before ()
GNode * 	g_node_insert_after ()
#define 	g_node_append()
GNode * 	g_node_prepend ()
#define 	g_node_insert_data()
#define 	g_node_insert_data_after()
#define 	g_node_insert_data_before()
#define 	g_node_append_data()
#define 	g_node_prepend_data()
void 	g_node_reverse_children ()
void 	g_node_traverse ()
gboolean 	(*GNodeTraverseFunc) ()
void 	g_node_children_foreach ()
void 	(*GNodeForeachFunc) ()
GNode * 	g_node_get_root ()
GNode * 	g_node_find ()
GNode * 	g_node_find_child ()
gint 	g_node_child_index ()
gint 	g_node_child_position ()
#define 	g_node_first_child()
GNode * 	g_node_last_child ()
GNode * 	g_node_nth_child ()
GNode * 	g_node_first_sibling ()
#define 	g_node_next_sibling()
#define 	g_node_prev_sibling()
GNode * 	g_node_last_sibling ()
#define 	G_NODE_IS_LEAF()
#define 	G_NODE_IS_ROOT()
guint 	g_node_depth ()
guint 	g_node_n_nodes ()
guint 	g_node_n_children ()
gboolean 	g_node_is_ancestor ()
guint 	g_node_max_height ()
void 	g_node_unlink ()
void 	g_node_destroy ()

函数功能分类

创建

GNode * g_node_new ()

复制

GNode * g_node_copy ()
GNode * g_node_copy_deep ()

插入

GNode * g_node_insert ()
GNode * g_node_insert_before ()
GNode * g_node_insert_after ()
#define g_node_append()
GNode * g_node_prepend ()
#define g_node_insert_data()
#define g_node_insert_data_after()
#define g_node_insert_data_before()
#define g_node_append_data()
#define g_node_prepend_data()

子节点反转

void g_node_reverse_children ()

遍历及子节点遍历

void g_node_traverse ()
void g_node_children_foreach ()

查找

GNode * g_node_get_root ()
GNode * g_node_find ()
GNode * g_node_find_child ()

定位

gint g_node_child_index ()
gint g_node_child_position ()
#define g_node_first_child()
GNode * g_node_last_child ()
GNode * g_node_nth_child ()
GNode * g_node_first_sibling ()
#define g_node_next_sibling()
#define g_node_prev_sibling()
GNode * g_node_last_sibling ()

判断

// 是否为叶子节点
#define G_NODE_IS_LEAF()
// 是否为树的根节点
#define G_NODE_IS_ROOT()

是否为节点的祖先

gboolean g_node_is_ancestor ()

节点深度

guint g_node_depth ()

节点编号

guint g_node_n_nodes ()

节点的子节点

guint g_node_n_children ()

树的最大高度

guint g_node_max_height ()

删除

void g_node_unlink ()

释放

void g_node_destroy ()

函数功能说明及综合演示

N叉树的综合演示

下面示例程序来自官方测试代码,演示了N叉树的创建、插入、查找、遍历、销毁等操作。
源码见glib_examples\glib_node\glib_node_basic

#include <glib.h>

#define	C2P(c)		((gpointer) ((long) (c)))
#define	P2C(p)		((gchar) ((gintptr) (p)))

static gboolean node_build_string (GNode *node, gpointer data)
{
    gchar **p = data;
    gchar *string;
    gchar c[2] = "_";

    c[0] = ((gchar) ((gintptr) (node->data)));

    string = g_strconcat (*p ? *p : "", c, NULL);
    g_free (*p);
    *p = string;

    return FALSE;
}

static void glib_node_basic_test (void)
{
    GNode *root;
    GNode *node;
    GNode *node_B;
    GNode *node_F;
    GNode *node_G;
    GNode *node_J;
    guint i;
    gchar *tstring, *cstring;

    root = g_node_new (C2P ('A'));
    g_assert (g_node_depth (root) == 1 && g_node_max_height (root) == 1);

    node_B = g_node_new (C2P ('B'));
    g_node_append (root, node_B);
    g_assert (root->children == node_B);

    g_node_append_data (node_B, C2P ('E'));
    g_node_prepend_data (node_B, C2P ('C'));
    g_node_insert (node_B, 1, g_node_new (C2P ('D')));

    node_F = g_node_new (C2P ('F'));
    g_node_append (root, node_F);
    g_assert (root->children->next == node_F);

    node_G = g_node_new (C2P ('G'));
    g_node_append (node_F, node_G);
    node_J = g_node_new (C2P ('J'));
    g_node_prepend (node_G, node_J);
    g_node_insert (node_G, 42, g_node_new (C2P ('K')));
    g_node_insert_data (node_G, 0, C2P ('H'));
    g_node_insert (node_G, 1, g_node_new (C2P ('I')));

    g_assert (g_node_depth (root) == 1);
    g_assert (g_node_max_height (root) == 4);
    g_assert (g_node_depth (node_G->children->next) == 4);
    g_assert (g_node_n_nodes (root, G_TRAVERSE_LEAFS) == 7);
    g_assert (g_node_n_nodes (root, G_TRAVERSE_NON_LEAFS) == 4);
    g_assert (g_node_n_nodes (root, G_TRAVERSE_ALL) == 11);
    g_assert (g_node_max_height (node_F) == 3);
    g_assert (g_node_n_children (node_G) == 4);
    g_assert (g_node_find_child (root, G_TRAVERSE_ALL, C2P ('F')) == node_F);
    g_assert (g_node_find (root, G_LEVEL_ORDER, G_TRAVERSE_NON_LEAFS, C2P ('I')) == NULL);
    g_assert (g_node_find (root, G_IN_ORDER, G_TRAVERSE_LEAFS, C2P ('J')) == node_J);

    for (i = 0; i < g_node_n_children (node_B); i++)
    {
    node = g_node_nth_child (node_B, i);
    g_assert (P2C (node->data) == ('C' + i));
    }

    for (i = 0; i < g_node_n_children (node_G); i++)
    g_assert (g_node_child_position (node_G, g_node_nth_child (node_G, i)) == i);

    /* we have built:                    A
    *                                 /   \
    *                               B       F
    *                             / | \       \
    *                           C   D   E       G
    *                                         / /\ \
    *                                       H  I  J  K
    *
    * for in-order traversal, 'G' is considered to be the "left"
    * child of 'F', which will cause 'F' to be the last node visited.
    */

    tstring = NULL;
    g_node_traverse (root, G_PRE_ORDER, G_TRAVERSE_ALL, -1, node_build_string, &tstring);
    g_assert_cmpstr (tstring, ==, "ABCDEFGHIJK");
    g_free (tstring); tstring = NULL;
    g_node_traverse (root, G_POST_ORDER, G_TRAVERSE_ALL, -1, node_build_string, &tstring);
    g_assert_cmpstr (tstring, ==, "CDEBHIJKGFA");
    g_free (tstring); tstring = NULL;
    g_node_traverse (root, G_IN_ORDER, G_TRAVERSE_ALL, -1, node_build_string, &tstring);
    g_assert_cmpstr (tstring, ==, "CBDEAHGIJKF");
    g_free (tstring); tstring = NULL;
    g_node_traverse (root, G_LEVEL_ORDER, G_TRAVERSE_ALL, -1, node_build_string, &tstring);
    g_assert_cmpstr (tstring, ==, "ABFCDEGHIJK");
    g_free (tstring); tstring = NULL;

    g_node_traverse (root, G_LEVEL_ORDER, G_TRAVERSE_LEAFS, -1, node_build_string, &tstring);
    g_assert_cmpstr (tstring, ==, "CDEHIJK");
    g_free (tstring); tstring = NULL;
    g_node_traverse (root, G_PRE_ORDER, G_TRAVERSE_NON_LEAFS, -1, node_build_string, &tstring);
    g_assert_cmpstr (tstring, ==, "ABFG");
    g_free (tstring); tstring = NULL;

    g_node_reverse_children (node_B);
    g_node_reverse_children (node_G);

    g_node_traverse (root, G_LEVEL_ORDER, G_TRAVERSE_ALL, -1, node_build_string, &tstring);
    g_assert_cmpstr (tstring, ==, "ABFEDCGKJIH");
    g_free (tstring); tstring = NULL;

    cstring = NULL;
    node = g_node_copy (root);
    g_assert (g_node_n_nodes (root, G_TRAVERSE_ALL) == g_node_n_nodes (node, G_TRAVERSE_ALL));
    g_assert (g_node_max_height (root) == g_node_max_height (node));
    g_node_traverse (root, G_IN_ORDER, G_TRAVERSE_ALL, -1, node_build_string, &tstring);
    g_node_traverse (node, G_IN_ORDER, G_TRAVERSE_ALL, -1, node_build_string, &cstring);
    g_assert_cmpstr (tstring, ==, cstring);
    g_free (tstring); tstring = NULL;
    g_free (cstring); cstring = NULL;
    g_node_destroy (node);

    g_node_destroy (root);

    /* allocation tests */

    root = g_node_new (NULL);
    node = root;

    for (i = 0; i < 2048; i++)
    {
        g_node_append (node, g_node_new (NULL));
        if ((i%5) == 4) {
            node = node->children->next;
        }
    }
    g_assert (g_node_max_height (root) > 100);
    g_assert (g_node_n_nodes (root, G_TRAVERSE_ALL) == 1 + 2048);

    g_node_destroy (root);

}

gint main(gint argc, gchar **argv)
{
    glib_node_basic_test();

    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值