1. 程式人生 > >Glib學習(2) 雙向連結串列 Doubly-Linked Lists

Glib學習(2) 雙向連結串列 Doubly-Linked Lists

首先貼出來glib庫的幫助文件網址

http://web.mit.edu/barnowl/share/gtk-doc/html/glib/glib-Doubly-Linked-Lists.html#g-list-find

由於雙向連結串列與單向連結串列的很多函式功能和名稱都是一樣的,這裡對一些函式就不細說了,具體有什麼不瞭解的可以通過上面給的網址瞭解。

函式先說一下雙向連結串列的結構體

GList

typedef struct {
  gpointer data;
  GList *next;
  GList *prev;
} GList;

Doubly-Linked Lists — linked lists containing integer values or pointers to data, with the ability to iterate over the list in both directions。


這個是雙向連結串列的官方描述,其中說的的資料可以是int型的值或者是指標型別,我覺得就是32為能夠表示的就可以了,你願意的話char型的也可以儲存,就是浪費空間而已。

然後是他所支援的功能函式


下面貼出例子程式,這裡就不分開單獨講解,因為很多和單鏈表相似的地方

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

static gint
sort(gconstpointer p1, gconstpointer p2)//排序函式,正向排序
{
    gint32 a, b;
    
    a = GPOINTER_TO_INT(p1);
    b = GPOINTER_TO_INT(p2);

    return (a > b ? +1 : a == b ? 0 : -1);
}

static gint
sort_r(gconstpointer p1, gconstpointer p2)//逆向排序
{
    gint32 a, b;
    
    a = GPOINTER_TO_INT(p1);
    b = GPOINTER_TO_INT(p2);

    return (a < b ? +1 : a == b ? 0 : -1);
}

static void
print(gpointer p1, gpointer p2)//列印函式,只打印P1
{
    g_printf("%d,", *(gint*)p1);
}

static void
test_list(void)
{
    GList *list = NULL;
    gint nums[10] = {0,1,2,3,4,5,6,7,8,9};

// GList* g_list_append(GList *list, gpointer data);//尾加,和單鏈表是一樣的功能
    list = g_list_append(list, &nums[1]);
    g_printf("The first item should be '%d' now.\t\tResult: %d.\n", nums[1], *(gint*)list->data);
// GList* g_list_prepend(GList *list, gpointer data);//頭加
    list = g_list_prepend(list, &nums[0]);
// GList* g_list_first(GList *list);//獲得頭指標
    g_printf("The first item should be '%d' now.\t\tResult: %d.\n", nums[0], *(gint*)g_list_first(list)->data);
// GList* g_list_insert(GList *list, gpointer data, gint position);//在position位置插入data資料
    list = g_list_insert(list, &nums[2], 2);
// GList* g_list_last(GList *list);         返回連結串列最後一個的指標
    g_printf("The last item should be '%d' now.\t\tResult: %d.\n", nums[2], *(gint*)g_list_last(list)->data);
// GList* g_list_insert_before(GList *list, GList *sibling, gpointer data);     在連結串列指標sibling處前面插入data資料,NULL是最後一個的指標
    list = g_list_insert_before(list, NULL, &nums[3]);
    g_printf("The last item should be '%d' now.\t\tResult: %d.\n", nums[3], *(gint*)g_list_last(list)->data);
// #define g_list_next (list)           在list指標處的下一個指標,這個和單鏈表的next是一樣的
    g_printf("The second item should be '%d' now.\t\tResult: %d.\n", nums[1], *(gint*)g_list_next(list)->data);
// #define g_list_previous (list)       這個是list指標處的前一個指標,這個是單鏈表無法容易做到的,雙向連結串列中的雙向優勢
    g_printf("The first item should be '%d' now.\t\tResult: %d.\n", nums[0], *(gint*)g_list_previous(g_list_next(list))->data);
// gint g_list_index(GList *list, gconstpointer data);  查詢data首次出現的位置
    g_printf("The index of '%d' should be '%d' now.\t\tResult: %d.\n", nums[2], 2, g_list_index(list, &nums[2]));
// gint g_list_position(GList *list, GList *llink);     返回link在list連結串列中的位置
    g_printf("The position of the third item should be 2 now.\t\tResult: %d.\n", g_list_position(list, g_list_next(list)->next));
// guint g_list_length(GList *list);        連結串列長度
    g_printf("The length of list should be 4 now.\t\tResult: %d.\n", g_list_length(list));
    
    GList *lt = NULL;
    gint i;
    
// GList* g_list_insert_sorted(GList *list, gpointer data, GCompareFunc func);      按照func的規則排序插入
    for (i = 4; i < 10; i++)
        lt = g_list_insert_sorted(lt, &nums[i], sort_r);//逆向排序插入,9,8,7,6,5,4
// GList* g_list_reverse(GList *list);      翻轉連結串列,翻轉後是正序了,4,5,6,7,8,9
    lt = g_list_reverse(lt);
    
    g_printf("The second half of list should be sored now.\nResult:");
// gpointer g_list_nth_data(GList *list, guint n);      返回在位置n的資料
    for (i = 4; i < 10; i++)
        g_printf("%d,",*(gint*)(g_list_nth_data(lt, i-4)));
    g_printf("\n");

// GList* g_list_concat(GList *list1, GList *list2);       拼接list1和list2,這裡的list2的內容並不是複製的,而是直接連線的
    list = g_list_concat(list, lt);
    g_printf("The list should have all items which should be sored now.\nResult:");
// void g_list_foreach(GList *list, GFunc func, gpointer user_data);    呼叫func函式去操作list的每個元素,前面print函式是列印了list中的元素,user_data是func的第二個引數
    g_list_foreach(list, print, NULL);
    g_printf("\n");

// GList* g_list_sort(GList *list, GCompareFunc compare_func);      將連結串列中的元素按照func的規則進行排序
    list = g_list_sort(list, sort_r);//逆向排序
    g_printf("The list should have all items which should be sored reversed now.\nResult:");
    g_list_foreach(list, print, NULL);
    g_printf("\n");

    GList *lb = NULL;
// GList* g_list_copy(GList *list);     複製連結串列,僅僅是指標的複製,並沒有進行資料的複製
    lb = g_list_copy(list);
    g_printf("The backup list should have the same item and sequence now.\nResult:");
// GList* g_list_nth(GList *list, guint n);     返回位置n的連結串列指標
    for (i = 0; i < 10; i++) {
        GList *ltmp = g_list_nth(lb, i);
        g_printf("%d,", *(gint*)ltmp->data);
    }
    g_printf("\n");

// GList* g_list_sort_with_data(GList *list, GCompareDataFunc compare_func, gpointer user_data);    和g_list_sort()函式一樣,只是能夠接受一個使用者引數user_data
    lb = g_list_sort_with_data(lb, (GCompareDataFunc)sort, NULL);
    g_printf("The backup list should have all items which should be sored now.\nResult:");
    g_list_foreach(lb, print, NULL);
    g_printf("\n");

    GList *lall = NULL;
    lall = g_list_concat(list, lb);
    g_printf("The concated list should have all items now.\nResult:");
    g_list_foreach(lall, print, NULL);
    g_printf("\n");

// GList* g_list_remove(GList *list, gconstpointer data);   刪除資料data,只刪除第一個出現的元素
    lall = g_list_remove(lall, &nums[0]);
    g_printf("The list should have only one '%d' item now.\nResult:", nums[0]);
    g_list_foreach(lall, print, NULL);
    g_printf("\n");

// GList* g_list_remove_all(GList *list, gconstpointer data);   刪除data,不僅僅是第一個,所有的都刪除
    lall = g_list_remove_all(lall, &nums[9]);
    g_printf("The list should not have '%d' item now.\nResult:", nums[9]);
    g_list_foreach(lall, print, NULL);
    g_printf("\n");
    
    GList *ll = NULL;
// GList* g_list_find(GList *list, gconstpointer data);         找到資料data在連結串列中的位置,返回元素指標
    g_printf("The list should find '%d' now.\t\tResutl: %d.\n", nums[0], (ll = g_list_find(lall, &nums[0])) ? *(gint*)ll->data : -1);
// GList* g_list_find_custom(GList *list, gconstpointer data, GCompareFunc func);       根據func條件查詢data,如果沒找到返回null
    g_printf("The list should not find '%d' now.\t\tResutl: %d.\n", nums[9], (ll = g_list_find_custom(lall, &nums[9], sort)) ? *(gint*)ll->data : -1);

// void g_list_free(GList *list);
    g_list_free(lall);
}

int
main(void)
{
    printf("BEGIN:\n************************************************************\n");
    test_list();
    printf("\n************************************************************\nDONE\n");
    return 0;
}

下面是執行結果:

[email protected]:~/16021/glibdemo$ ls
Doubly_Linked_Lists.c  glist  hello  helloworld.c  slist  slist.c
[email protected]:~/16021/glibdemo$ gcc -o Doubly_Linked_Lists Doubly_Linked_Lists.c -lglib-2.0
[email protected]:~/16021/glibdemo$ ls
Doubly_Linked_Lists  Doubly_Linked_Lists.c  glist  hello  helloworld.c  slist  slist.c

[email protected]:~/16021/glibdemo$ ./Doubly_Linked_Lists 
BEGIN:
************************************************************
The first item should be '1' now.               Result: 1.
The first item should be '0' now.               Result: 0.
The last item should be '2' now.                Result: 2.
The last item should be '3' now.                Result: 3.
The second item should be '1' now.              Result: 1.
The first item should be '0' now.               Result: 0.
The index of '2' should be '2' now.             Result: 2.
The position of the third item should be 2 now.         Result: 2.
The length of list should be 4 now.             Result: 4.
The second half of list should be sored now.
Result:4,5,6,7,8,9,
The list should have all items which should be sored now.
Result:0,1,2,3,4,5,6,7,8,9,
The list should have all items which should be sored reversed now.
Result:9,8,7,6,5,4,3,2,1,0,
The backup list should have the same item and sequence now.
Result:9,8,7,6,5,4,3,2,1,0,
The backup list should have all items which should be sored now.
Result:0,1,2,3,4,5,6,7,8,9,
The concated list should have all items now.
Result:9,8,7,6,5,4,3,2,1,0,0,1,2,3,4,5,6,7,8,9,
The list should have only one '0' item now.
Result:9,8,7,6,5,4,3,2,1,0,1,2,3,4,5,6,7,8,9,
The list should not have '9' item now.
Result:8,7,6,5,4,3,2,1,0,1,2,3,4,5,6,7,8,
The list should find '0' now.           Resutl: 0.
The list should not find '9' now.               Resutl: -1.


************************************************************
DONE
[email protected]:~/16021/glibdemo$