在上一篇文章里我介绍了glib库中单向链表的用法,这篇文章介绍glib库双向链表的用法,还是沿用上一篇文章的风格,采用在代码中加入注释来说明代码,最后贴出程序的运行结果,然后加以少量说明。
双向链表与单向链表的区别是,从一个节点,不仅能访问到它的下一个节点,还能访问到它的上一个节点,其定义如下:
struct GList
{
gpointer data;
GList *next;
GList *prev;
};
在这里可以看到双向链表比单向链表多了一个指向上一个节点的指针prev。下面给出一段双向链表的演示代码:
/*
* file: g_list.c
* desc: 这个文件用于演示glib库里双向链表GList的用法
* compile: gcc -o g_list g_list.c `pkg-config --cflags --libs glib-2.0`
*/
#include <glib.h>
void display_list(GList *list)
{
GList *it = NULL;
/* 遍历链表 */
for (it = list; it; it = it->next) {
printf("%s", it->data);
}
printf("/n");
}
int main(int argc, char *argv[])
{
GList *list = NULL;
/*
* 向链表尾部追加节点
*/
list = g_list_append(list, "one ");
list = g_list_append(list, "two ");
list = g_list_append(list, "three ");
list = g_list_append(list, "four ");
list = g_list_append(list, "five ");
display_list(list);
/* 在链表头部插入*/
list = g_list_prepend(list, "zero ");
display_list(list);
GList *it = NULL;
/* 查找链表中的节点 */
it = g_list_find(list, "two ");
printf("Find data "two ": %s/n", it->data);
int index = 0;
/* 确定链表指针指向链表中的第几个节点 */
index = g_list_position(list, it);
printf("index of "two " is: %d/n", index);
it = g_list_nth(list, 1);
printf("%s/n", it->data);
/* 从链表里删除一个节点 */
printf("After remove data "three ", the list:/n");
list = g_list_remove(list, "three ");
display_list(list);
/* 向链表里插入一个节点 */
printf("After insert string "INSERT " at index 3, the list:/n");
list = g_list_insert(list, "INSERT ", 3);
display_list(list);
/* 采用内循环遍历链表节点 */
g_list_foreach(list, (GFunc)printf, NULL);
printf("/n");
GList *last = NULL;
/* 取链表的最后一个节点 */
last = g_list_last(list);
/* 从最后一个节点开始遍历链表 */
for (it = last; it; it = it->prev) { printf("%s", it->data); } printf("/n"); /* 销毁链表 */ g_list_free(list); return 0;}
在linux下使用下面的命令编译:
gcc -o g_list g_list.c `pkg-config --cflags --libs glib-2.0`
编译后程序运行的结果如下:
$ ./g_list
one two three four five
zero one two three four five
Find data "two ": two
index of "two " is: 2
one
After remove data "three ", the list:
zero one two four five
After insert string "INSERT " at index 3, the list:
zero one two INSERT four five
zero one two INSERT four five
five four INSERT two one zero
现在你应该知道我为什么在每个字符串后面加一个空格了吧。
总结:在glib库中,双向链表的用法跟单向链表基本上是一致的,只是多了一个访问上一个节点的指针prev。对于你的应用如果单向链表够用,就没有必要使用双向链表,因为这里要增加维护一个指针的开销。