glib 单向链表
原文地址: http://oss.lzu.edu.cn/modules/newbb/viewtopic.php?topic_id=498&forum=13&move=next
参考地址: http://hi.baidu.com/study_together/blog/item/efa7723a86d28ffe3b87ce3c.html
编译:gcc -g -Wall -O0 fuck.c -o fuck `pkg-config --libs --cflags glib-2.0`
1
创建、添加和销毁
下面的代码将初始化一个 GSList,向其添加两个条目,打印出列表的长度,然后释放它:
#include <stdio.h>
int main(int argc, char** argv) {
GSList* list = NULL;
printf("The list is now %d items long\n", g_slist_length(list));
list = g_slist_append(list, "first");
list = g_slist_append(list, "second");
printf("The list is now %d items long\n", g_slist_length(list));
g_slist_free(list);
return 0;
}
The list is now 0 items long
The list is now 2 items long
2
添加然后删除数据
可以添加数据;可能还会需要将其删除。这里是一个示例:
#include <stdio.h>
int main(int argc, char** argv) {
GSList* list = NULL;
list = g_slist_append(list, "second");
list = g_slist_prepend(list, "first");
printf("The list is now %d items long\n", g_slist_length(list));
list = g_slist_remove(list, "first");
printf("The list is now %d items long\n", g_slist_length(list));
g_slist_free(list);
return 0;
}
The list is now 2 items long
The list is now 1 items long
3
删除重复的条目
这里是当在一个列表中有重复的条目时会发生的问题:
#include <stdio.h>
int main(int argc, char** argv) {
GSList* list = NULL;
list = g_slist_append(list, "first");
list = g_slist_append(list, "second");
list = g_slist_append(list, "second");
list = g_slist_append(list, "third");
list = g_slist_append(list, "third");
printf("The list is now %d items long\n", g_slist_length(list));
list = g_slist_remove(list, "second");
list = g_slist_remove_all(list, "third");
printf("The list is now %d items long\n", g_slist_length(list));
g_slist_free(list);
return 0;
}
The list is now 5 items long
The list is now 2 items long
4
最后一个、第 n 个 和第 n 个数据
在 GSList 中有了一些条目后,可以通过不同的方式提取它们。这里是一些示例,并在 printf 语句中给出了解释。
#include <stdio.h>
int main(int argc, char** argv) {
GSList* list = NULL;
list = g_slist_append(list, "first");
list = g_slist_append(list, "second");
list = g_slist_append(list, "third");
printf("The last item is '%s'\n", g_slist_last(list)->data);
printf("The item at index '1' is '%s'\n", g_slist_nth(list, 1)->data);
printf("Now the item at index '1' the easy way: '%s'\n", g_slist_nth_data(list, 1));
printf("And the 'next' item after first item is '%s'\n", g_slist_next(list)->data);
g_slist_free(list);
return 0;
}
The last item is 'third'
The item at index '1' is 'second'
Now the item at index '1' the easy way: 'second'
And the 'next' item after first item is 'second'
5
使用用户定义的类型
到现在为止我们一直在使用字符串;也就是说,我们只是将指向字符的指针放入到 GSList 中。在下面的代码示例中,
将会定义一个 Person 结构体,并将这个结构体的一些实例放入到 GSList 中:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
char* name;
int shoe_size;
} Person;
int main(int argc, char** argv) {
GSList* list = NULL;
Person* tom = (Person*)malloc(sizeof(Person));
tom->name = "Tom";
tom->shoe_size = 12;
list = g_slist_append(list, tom);
Person* fred = g_new(Person, 1); // allocate memory for one Person struct
fred->name = "Fred";
fred->shoe_size = 11;
list = g_slist_append(list, fred);
printf("Tom's shoe size is '%d'\n", ((Person*)list->data)->shoe_size);
printf("The last Person's name is '%s'\n", ((Person*)g_slist_last(list)->data)->name);
g_slist_free(list);
free(tom);
g_free(fred);
return 0;
}
Tom's shoe size is '12'
The last Person's name is 'Fred'
6
组合、反转,等等
GSList 附带了一些便利的工具,可以连接和反转列表。这里是它们的工作方式:
#include <stdio.h>
int main(int argc, char** argv) {
GSList* list1 = NULL;
list1 = g_slist_append(list1, "first");
list1 = g_slist_append(list1, "second");
GSList* list2 = NULL;
list2 = g_slist_append(list2, "third");
list2 = g_slist_append(list2, "fourth");
GSList* both = g_slist_concat(list1, list2);
printf("The third item in the concatenated list is '%s'\n", g_slist_nth_data(both, 2));
GSList* reversed = g_slist_reverse(both);
printf("The first item in the reversed list is '%s'\n", reversed->data);
g_slist_free(reversed);
return 0;
}
The third item in the concatenated list is 'third'
The first item in the reversed list is 'fourth'
7
简单遍历
这里是遍历 GSList 中所有内容的一个直观方法:
#include <stdio.h>
int main(int argc, char** argv) {
GSList* list = NULL, *iterator = NULL;
list = g_slist_append(list, "first");
list = g_slist_append(list, "second");
list = g_slist_append(list, "third");
for (iterator = list; iterator; iterator = iterator->next) {
printf("Current item is '%s'\n", iterator->data);
}
g_slist_free(list);
return 0;
}
Current item is 'first'
Current item is 'second'
Current item is 'third'
迭代器(iterator)
8
使用函数进行高级遍历
遍历列表的另一种方法是使用 g_slist_foreach,并提供一个将为列表中的每一个条目调用的函数。
#include <stdio.h>
void print_iterator(gpointer item, gpointer prefix) {
printf("%s %s\n", prefix, item);
}
void print_iterator_short(gpointer item) {
printf("%s\n", item);
}
int main(int argc, char** argv) {
GSList* list = g_slist_append(NULL, g_strdup("first"));
list = g_slist_append(list, g_strdup("second"));
list = g_slist_append(list, g_strdup("third"));
printf("Iterating with a function:\n");
g_slist_foreach(list, print_iterator, "-->");
printf("Iterating with a shorter function:\n");
g_slist_foreach(list, (GFunc)print_iterator_short, NULL);
printf("Now freeing each item\n");
g_slist_foreach(list, (GFunc)g_free, NULL);
g_slist_free(list);
return 0;
}
Iterating with a function:
--> first
--> second
--> third
Iterating with a shorter function:
first
second
third
Now freeing each item
9
使用 GCompareFunc 排序
可以通过提供一个知道如何比较列表中条目的函数来对 GSLit 进行排序。下面的示例展示了对字符串列表进行排序的一种方法:
#include <stdio.h>
gint my_comparator(gconstpointer item1, gconstpointer item2) {
return g_ascii_strcasecmp(item1, item2);
}
int main(int argc, char** argv) {
GSList* list = g_slist_append(NULL, "Chicago");
list = g_slist_append(list, "Boston");
list = g_slist_append(list, "Albany");
list = g_slist_sort(list, (GCompareFunc)my_comparator);
printf("The first item is now '%s'\n", list->data);
printf("The last item is now '%s'\n", g_slist_last(list)->data);
g_slist_free(list);
return 0;
}
The first item is now 'Albany'
The last item is now 'Chicago'
10
查找元素
有一些方法可以在 GSList 查找元素。已经介绍了如何简单地遍历列表的全部内容,比较每个条目,直到找到了目标条目。
如果已经拥有了要寻找的数据,而只是想要获得它在列表中的位置,那么可以使用 g_slist_find。最后,可以使用 g_slist_find_custom,
它允许您使用一个函数来检查列表中的每一个条目。下面展示了 g_slist_find 和 g_slist_find_custom:
#include <stdio.h>
gint my_finder(gconstpointer item) {
return g_ascii_strcasecmp(item, "second");
}
int main(int argc, char** argv) {
GSList* list = g_slist_append(NULL, "first");
list = g_slist_append(list, "second");
list = g_slist_append(list, "third");
GSList* item = g_slist_find(list, "second");
printf("This should be the 'second' item: '%s'\n", item->data);
item = g_slist_find_custom(list, NULL, (GCompareFunc)my_finder);
printf("Again, this should be the 'second' item: '%s'\n", item->data);
item = g_slist_find(list, "delta");
printf("'delta' is not in the list, so we get: '%s'\n", item ? item->data : "(null)");
g_slist_free(list);
return 0;
}
This should be the 'second' item: 'second'
Again, this should be the 'second' item: 'second'
'delta' is not in the list, so we get: '(null)'
11
通过插入进行高级添加
既然已经接触过几次 GCompareFunc,一些更有趣的插入操作会更有意义。使用 g_slist_insert 可以将条目插入到指定的位置,
使用 g_slist_insert_before 可以将条目插入到特定位置之前,使用 g_slist_insert_sorted 可以进行有序插入。这里是样例:
#include <stdio.h>
int main(int argc, char** argv) {
GSList* list = g_slist_append(NULL, "Anaheim "), *iterator = NULL;
list = g_slist_append(list, "Elkton ");
printf("Before inserting 'Boston', second item is: '%s'\n", g_slist_nth(list, 1)->data);
g_slist_insert(list, "Boston ", 1);
printf("After insertion, second item is: '%s'\n", g_slist_nth(list, 1)->data);
list = g_slist_insert_before(list, g_slist_nth(list, 2), "Chicago ");
printf("After an insert_before, third item is: '%s'\n", g_slist_nth(list, 2)->data);
list = g_slist_insert_sorted(list, "Denver ", (GCompareFunc)g_ascii_strcasecmp);
printf("After inserting 'Denver', here's the final list:\n");
g_slist_foreach(list, (GFunc)printf, NULL);
g_slist_free(list);
return 0;
}
Before inserting 'Boston', second item is: 'Elkton '
After insertion, second item is: 'Boston '
After an insert_before, third item is: 'Chicago '
After inserting 'Denver', here's the final list:
Anaheim Boston Chicago Denver Elkton
12
自定义数据结构排序 (根据字符)
#include <glib.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct {
char* name;
int shoe_size;
} Person;
gint my_comparator(gconstpointer item1, gconstpointer item2) {
return g_ascii_strcasecmp(((Person*)item1)->name, ((Person*)item2)->name);
}
int main(int argc, char** argv) {
GSList* list = NULL;
Person* tom = (Person*)malloc(sizeof(Person));
tom->name = "Tom";
tom->shoe_size = 12;
list = g_slist_append(list, tom);
Person* fred = g_new(Person, 1); // allocate memory for one Person struct
fred->name = "Fred";
fred->shoe_size = 11;
list = g_slist_append(list, fred);
Person* god = g_new(Person, 1); // allocate memory for one Person struct
god->name = "zod";
god->shoe_size = 15;
list = g_slist_append(list, god);
list = g_slist_sort(list, (GCompareFunc)my_comparator);
printf("Tom's shoe size is '%d'\n", ((Person*)list->data)->shoe_size);
printf("The last Person's name is '%s'\n", ((Person*)g_slist_last(list)->data)->name);
g_slist_free(list);
free(tom);
g_free(fred);
g_free(god);
return 0;
}
***** Output *****
Tom's shoe size is '11'
The last Person's name is 'zod'
13 自定义数据结构排序(根据数字)
#include <glib.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct {
char* name;
int shoe_size;
} Person;
gint my_comparator(gconstpointer item1, gconstpointer item2) {
if(((Person*)item1)->shoe_size > ((Person*)item2)->shoe_size)
{
return 1;
}
else
{
return 0;
}
// return g_ascii_strcasecmp(((Person*)item1)->name, ((Person*)item2)->name);
}
int main(int argc, char** argv) {
GSList* list = NULL;
Person* tom = (Person*)malloc(sizeof(Person));
tom->name = "Tom";
tom->shoe_size = 10;
list = g_slist_append(list, tom);
Person* fred = g_new(Person, 1); // allocate memory for one Person struct
fred->name = "yred";
fred->shoe_size = 11;
list = g_slist_append(list, fred);
Person* god = g_new(Person, 1); // allocate memory for one Person struct
god->name = "zod";
god->shoe_size = 15;
list = g_slist_append(list, god);
list = g_slist_sort(list, (GCompareFunc)my_comparator);
printf("Tom's shoe size is '%d'\n", ((Person*)list->data)->shoe_size);
printf("The last Person's name is '%s'\n", ((Person*)g_slist_last(list)->data)->name);
g_slist_free(list);
free(tom);
g_free(fred);
g_free(god);
return 0;
}
*******output*******
Tom's shoe size is '10'
The last Person's name is 'zod'
完