glib库双向链表GList详解
glib库中的GList是双向链表结构,与单向链表相比,每个节点不仅保存指向下一个节点的指针,还保存指向前一个节点的指针,便于双向遍历。其结构定义如下:
typedef struct _GList GList;
struct _GList {
gpointer data;
GList *next;
GList *prev;
};
下面是演示GList基本操作的完整代码,包含插入、删除、查找、遍历等常用功能:
/*
* 文件: g_list_demo.c
* 说明: glib双向链表GList使用示例
* 编译: gcc -o g_list_demo g_list_demo.c `pkg-config --cflags --libs glib-2.0`
*/
#include <glib.h>
// 打印链表所有节点数据
void print_list(GList *list) {
for (GList *iter = list; iter != NULL; iter = iter->next) {
printf("%s", (char*)iter->data);
}
printf("\n");
}
int main(int argc, char *argv[]) {
GList *glist = NULL;
// 尾部追加节点
glist = g_list_append(glist, "one ");
glist = g_list_append(glist, "two ");
glist = g_list_append(glist, "three ");
glist = g_list_append(glist, "four ");
glist = g_list_append(glist, "five ");
print_list(glist);
// 头部插入节点
glist = g_list_prepend(glist, "zero ");
print_list(glist);
GList *found = NULL;
// 查找包含数据"two "的节点
found = g_list_find(glist, "two ");
if (found) {
printf("找到节点数据: %s\n", (char*)found->data);
}
// 获取节点在链表中的索引位置
gint pos = g_list_position(glist, found);
printf("节点索引: %d\n", pos);
// 获取指定索引的节点
GList *node = g_list_nth(glist, 1);
printf("索引1的节点数据: %s\n", (char*)node->data);
// 删除指定数据的节点
glist = g_list_remove(glist, "three ");
printf("删除'three '后: ");
print_list(glist);
// 在指定位置插入节点
glist = g_list_insert(glist, "INSERT ", 3);
printf("索引3插入'INSERT '后: ");
print_list(glist);
// 使用foreach遍历
g_list_foreach(glist, (GFunc)printf, NULL);
printf("\n");
// 反向遍历
GList *tail = g_list_last(glist);
printf("反向遍历: ");
for (GList *iter = tail; iter != NULL; iter = iter->prev) {
printf("%s", (char*)iter->data);
}
printf("\n");
// 释放链表内存
g_list_free(glist);
return 0;
}
编译命令:
gcc -o g_list_demo g_list_demo.c `pkg-config --cflags --libs glib-2.0`
运行结果:
$ ./g_list_demo
one two three four five
zero one two three four five
找到节点数据: two
节点索引: 2
索引1的节点数据: one
删除'three '后: zero one two four five
索引3插入'INSERT '后: zero one two INSERT four five
zero one two INSERT four five
反向遍历: five four INSERT two one zero
代码中每个字符串末尾包含空格,目的是使输出更易读。
总体而言,GList的API与GSList(单向链表)高度相似,主要区别在于GList增加了prev指针对反向遍历的支持。开发者应根据实际需求选择:若只需单向遍历,单向链表更节省内存和性能;若需要高效的逆向访问或频繁在链表中间插入/删除,双向链表更合适。