首页 > 其他分享 >【glibc】glib库单向链表GSList介绍

【glibc】glib库单向链表GSList介绍

时间:2024-01-22 11:14:08浏览次数:40  
标签:glib slist GSList list two 链表 printf

glib库单向链表介绍

glib库里实现了一些基本的数据结构,比如单向链表,双向链表、队列、树、hash表和数组。这篇文章里我主要介绍在linux平台下使用glib库中的单向链表进行编程,以后的文章我会陆续介绍双向链表、队列和其它数据结构的用法。

单向链表(即GSList)是glib库里最简单的容具,它把一系列的节点链接在一起,可以从一个节点访问到下一个节点。glib库里对GSList结构的定义如下:

struct  GSList
{
  gpointer data;
  GSList *next;
} ;

data成员定义为gpointer(即void*),可以放任何类型的数据。下面举个例子来说明怎么使用GSList来创建、添加、插入、排序、反转和销毁单向链表。

#include  < glib.h >

void  display_list(GSList  * list)
{
    GSList  * iterator  =  NULL;

     for  (iterator  =  list; iterator; iterator  =  iterator -> next) {
        printf( " %s  " , ( char * )iterator -> data);
    }
    printf( " /n " );
}

int  my_str_cmp(gconstpointer str1, gconstpointer str2)
{
     return  strcmp(str1, str2);
}

int  main( int  argc,  char   * argv[])
{
    GSList  * list  =  NULL;

     /*
     * 这里没有调用创建链表的函数,只需要声明一个指向GSList结构体的指针,
     * g_slist_append函数返回指向链表首部的指针,所以一定要保存这个指针
      */
    printf( " Creat single list:/n " );
    list  =  g_slist_append(list,  " one " );
    list  =  g_slist_append(list,  " two " );
    list  =  g_slist_append(list,  " three " );
    display_list(list);

     /*
     * 在链表首部加入,复杂度是O(1),记得要保存函数返回的指针
      */
    printf( " Add at head of list:/n " );
    list  =  g_slist_prepend(list,  " first " );
    list  =  g_slist_prepend(list,  " second " );
    list  =  g_slist_prepend(list,  " third " );
    display_list(list);

     /*
     * 在链表的指定位置插入一个节点
      */
    printf( " Insert at index 1, 2, 3:/n " );
    list  =  g_slist_insert(list,  " 1 " ,  1 );
    list  =  g_slist_insert(list,  " 2 " ,  2 );
    list  =  g_slist_insert(list,  " 3 " ,  3 );
    display_list(list);

     /*
     * 向链表中插入节点并排序,这里我传入了一个用于排序链表元素的比较函数,
     * 这个函数只是简单的调用了strcmp。这里可以直接到strcmp作为第三个参数
     * 传给g_slist_insert_sorted
      */
    printf( " Insert sorted:/n " );
    list  =  g_slist_insert_sorted(list,  " ONE " , my_str_cmp);
    list  =  g_slist_insert_sorted(list,  " TWO " , my_str_cmp);
    list  =  g_slist_insert_sorted(list,  " THREE " , my_str_cmp);
    display_list(list);

     /*
     * 反转链表
      */
    printf( " Reverse the list:/n " );
    list  =  g_slist_reverse(list);
    display_list(list);

     /*
     * 删除链表,如果list为NULL的话,g_slist_free函数会直接返回
      */
    g_slist_free(list);
     return   0 ;
}

程序的运行结果如下:

Creat single list:
one two three
Add at head of list:
third second first one two three
Insert at index 1, 2, 3:
third 1 2 3 second first one two three
Insert sorted:
ONE THREE TWO third 1 2 3 second first one two three
Reverse the list:
three two one first second 3 2 1 third TWO THREE ONE

从上面的例子里我们可以看到,使用一个单向链表前只需要声明一个指向GSList结构的指针就可以了,声明该指 针以后就可以用该指针来对链表进行操作,只需要记住每次对链表进行操作后,都要保存返回的链表头指针就可以了。

下面的一个例子用于演法对单链表的查找、删除与合并。

#include  < glib.h >

void  display_list(GSList  * list)
{
    GSList  * iterator  =  NULL;

     for  (iterator  =  list; iterator; iterator  =  iterator -> next) {
        printf( " %s  " , ( char * ) iterator -> data);
    }
    printf( " /n " );
}

int  main( int  argc,  char   * argv[])
{
    GSList  * list  =  NULL;

    printf( " Create single list:/n " );
    list  =  g_slist_append(list,  " one " );
    list  =  g_slist_append(list,  " two " );
    list  =  g_slist_append(list,  " three " );
    list  =  g_slist_append(list,  " four " );
    list  =  g_slist_append(list,  " five " );
    display_list(list);

    GSList  * it  =  NULL;

     /*
     * 查找内容为"three"的节点,返回指向找到的第一个节点的指针
      */
    printf( " Find data "three" in the list:/n " );
    it  =  g_slist_find(list,  " three " );
    printf( " %s " , ( char * ) it -> data);

     /*
     * 查找第三个节点,链表里节点的索引号为0,1,2...
     * 如果超出链表尾部(链表长度小于3)返回NULL
      */
    printf( " Data of the 3rd item:/n " );
    it  =  g_slist_nth(list,  2 );
     if  (it  !=  NULL) {
        printf( " %s " , ( char * ) it -> data);
    }

     /*
     * 取第5个节点的数据,如果超出链表尾部,返回NULL
      */
    printf( " Data of the 5th item:/n " );
    printf( " %s " , g_slist_nth_data(list,  4 ));

    list  =  g_slist_append(list,  " two " );
    display_list(list);
    
     /*
     * 删除数据为"two"的节点,这里只会删除找到的第一个节点,
     * 后面的节点不会被删除
      */
    printf( " Remove the first data "two" from the list:/n " );
    list  =  g_slist_remove(list,  " two " );
    display_list(list);

     /*
     * 另一种删除节点的方法,先把节点从链表里删除,再删除节点的数据
      */
    printf( " Remove the 3rd item from list:/n " );
    it  =  g_slist_nth(list,  2 );

     /*  执行完下面这一步it->next==NULL  */
    list  =  g_slist_remove_link(list, it);
    
     /*  删除节点及其数据  */
    g_slist_free_1(it);
    display_list(list);

    GSList  * list2  =  NULL;
    
    printf( " The second list:/n " );
    list2  =  g_slist_append(list2,  " six " );
    list2  =  g_slist_append(list2,  " seven " );
    list2  =  g_slist_append(list2,  " eight " );
    display_list(list2);

     /*
     * 合并两个链表
      */
    printf( " Concat two lists:/n " );
    list  =  g_slist_concat(list, list2);
    display_list(list);

    g_slist_free(list);
     return   0 ;
}

程序的运行结果如下:

Creat single list:
one two three
Add at head of list:
third second first one two three
Insert at index 1, 2, 3:
third 1 2 3 second first one two three
Insert sorted:
ONE THREE TWO third 1 2 3 second first one two three
Reverse the list:
three two one first second 3 2 1 third TWO THREE ONE

从上面的例子里我们可以看到,使用一个单向链表前只需要声明一个指向GSList结构的指针就可以了,声明该指 针以后就可以用该指针来对链表进行操作,只需要记住每次对链表进行操作后,都要保存返回的链表头指针就可以了。

下面的一个例子用于演法对单链表的查找、删除与合并。

#include  < glib.h >

void  display_list(GSList  * list)
{
    GSList  * iterator  =  NULL;

     for  (iterator  =  list; iterator; iterator  =  iterator -> next) {
        printf( " %s  " , ( char * ) iterator -> data);
    }
    printf( " /n " );
}

int  main( int  argc,  char   * argv[])
{
    GSList  * list  =  NULL;

    printf( " Create single list:/n " );
    list  =  g_slist_append(list,  " one " );
    list  =  g_slist_append(list,  " two " );
    list  =  g_slist_append(list,  " three " );
    list  =  g_slist_append(list,  " four " );
    list  =  g_slist_append(list,  " five " );
    display_list(list);

    GSList  * it  =  NULL;

     /*
     * 查找内容为"three"的节点,返回指向找到的第一个节点的指针
      */
    printf( " Find data "three" in the list:/n " );
    it  =  g_slist_find(list,  " three " );
    printf( " %s " , ( char * ) it -> data);

     /*
     * 查找第三个节点,链表里节点的索引号为0,1,2...
     * 如果超出链表尾部(链表长度小于3)返回NULL
      */
    printf( " Data of the 3rd item:/n " );
    it  =  g_slist_nth(list,  2 );
     if  (it  !=  NULL) {
        printf( " %s " , ( char * ) it -> data);
    }

     /*
     * 取第5个节点的数据,如果超出链表尾部,返回NULL
      */
    printf( " Data of the 5th item:/n " );
    printf( " %s " , g_slist_nth_data(list,  4 ));

    list  =  g_slist_append(list,  " two " );
    display_list(list);
    
     /*
     * 删除数据为"two"的节点,这里只会删除找到的第一个节点,
     * 后面的节点不会被删除
      */
    printf( " Remove the first data "two" from the list:/n " );
    list  =  g_slist_remove(list,  " two " );
    display_list(list);

     /*
     * 另一种删除节点的方法,先把节点从链表里删除,再删除节点的数据
      */
    printf( " Remove the 3rd item from list:/n " );
    it  =  g_slist_nth(list,  2 );

     /*  执行完下面这一步it->next==NULL  */
    list  =  g_slist_remove_link(list, it);
    
     /*  删除节点及其数据  */
    g_slist_free_1(it);
    display_list(list);

    GSList  * list2  =  NULL;
    
    printf( " The second list:/n " );
    list2  =  g_slist_append(list2,  " six " );
    list2  =  g_slist_append(list2,  " seven " );
    list2  =  g_slist_append(list2,  " eight " );
    display_list(list2);

     /*
     * 合并两个链表
      */
    printf( " Concat two lists:/n " );
    list  =  g_slist_concat(list, list2);
    display_list(list);

    g_slist_free(list);
     return   0 ;
}

程序的运行结果如下:

Create single list:
one two three four five
Find data "three" in the list:
three
Data of the 3rd item:
three
Data of the 5th item:
five
one two three four five two
Remove the first data "two" from the list:
one three four five two
Remove the 3rd item from list:
one three five two
The second list:
six seven eight
Concat two lists:
one three five two six seven eight

通过上面的两个子例我们可以看到,glib库中的单链表操作是很简单的。在这么多函数调用里,我们还可以发现glib库中操作数据结构的函数命名规则:g_容器名_函数名。对于我后面的文章将要讲到的双向链表、队列、树、hash表和数组,这一命名规则同样适用。

glib库的更多参考:
http://developer.gnome.org/doc/API/glib/index.html
http://developer.gnome.org/doc/API/2.0/glib/index.html

 

标签:glib,slist,GSList,list,two,链表,printf
From: https://www.cnblogs.com/opensmarty/p/17979608

相关文章

  • 【glibc】glib 数组
    编译:gcc-g-Wall-O0fuck.c-ofuck`pkg-config--libs--cflagsglib-2.0`1基本操作这里是向数组添加和删除数据的一些主要方法:#include<glib.h>#include<stdio.h>intmain(intargc,char**argv){GArray*a=g_array_new(FALSE,FALSE,sizeof(char*));......
  • 【glibc】glib库双向链表GList介绍
    在上一篇文章里我介绍了glib库中单向链表的用法,这篇文章介绍glib库双向链表的用法,还是沿用上一篇文章的风格,采用在代码中加入注释来说明代码,最后贴出程序的运行结果,然后加以少量说明。双向链表与单向链表的区别是,从一个节点,不仅能访问到它的下一个节点,还能访问到它的上一个节点,其......
  • 【glibc】glib库数组GArray介绍
    glib库中的数组GArray类型很像C++标准容器库中的vector容器。要使用glib库中的数组中需要声明一个指向GArray类型的指针。GArray的定义如下:structGArray{gchar*data;guintlen;};然后就可以在这个数组前或者数组后添加数据,添加数据的时候数组也会像C++中的vector容器......
  • 【glibc】glib库hash表GHashTable介绍
    hash表是一种提供key-value访问的数据结构,通过指定的key值可以快速的访问到与它相关联的value值。hash表的一种典型用法就是字典,通过单词的首字母能够快速的找到单词。关于hash表的详细介绍请查阅数据结构的相关书籍,我这里只介绍glib库中hash表的基本用法。要使用一个hash表首先必......
  • 【glibc】glib库队列GQueue介绍
    队列是一种向最后添加条目,从最前删除条目的数据结构,这种数据结构在处理按顺序到达的数据是很有用。glib库提供的队列GQueue是一个双端队列,它的实现基础是双向链表,所以它支持在队列的两端进行添加和删除,也支持很多其它的操作,比如在队列中进行插入和删除,但是我不推荐使用这样的功能......
  • 链表
    1.设计链表力扣707-单链表classListNode{intval;ListNodenext;ListNode(intval){this.val=val;}}classMyLinkedList{intsize;ListNodehead;//虚拟头节点publicMyLinkedList(){size=0;head=......
  • C++U3-第11课-单、双链表
    学习目标 链表概念计算机存储结构 单链表 实现单链表       删除 插入节点  双向链表  实现双链表         [【数据结构-链表】猴子选大王] 【题意分析】通过循环报数的方式每一次剔除......
  • spring--CGLIB动态代理的实现原理
    CGLIB(CodeGenerationLibrary)是一个强大的、高性能、高质量的代码生成库,它可以在运行时扩展Java类和实现Java接口。CGLIB动态代理是基于继承的方式来实现的,它不需要接口,可以代理普通类。以下是CGLIB动态代理的实现原理:继承:CGLIB动态代理通过继承目标类来创建子类,并在......
  • spring--JDK动态代理和CGLIB代理的区别
    JDK动态代理和CGLIB代理是Java中常用的两种动态代理实现方式,它们各有特点和适用场景:JDK动态代理:JDK动态代理是基于接口的代理方式,它使用Java反射机制来创建代理对象,并要求目标对象实现一个或多个接口。在代理过程中,JDK动态代理会创建一个实现了目标对象所有接口的代......
  • 148.排序链表
    1.题目介绍给你链表的头结点head,请将其按升序排列并返回排序后的链表。示例1:输入:head=[4,2,1,3]输出:[1,2,3,4]2.题解在147.对链表进行插入排序中我们使用插入排序的方式对于链表进行排序插入排序的时间复杂度是O(n^2),其中n是链表的长度。这道题考虑时间复杂度......