Glib学习(3) 双端队列 Double-ended Queues

来源:互联网 发布:java io流写入文件 编辑:程序博客网 时间:2024/05/21 21:45

在数据结构中两种重要的类型就是队列和栈,而什么又是双端队列呢?

双端队列是一个限定插入和删除操作的数据结构,具有队列和的性质。

(deque,全名double-ended queue)是一种具有队列和栈的性质的数据结构。双端队列中的元素可以从两端弹出,其限定插入和删除操作在表的两端进行。

也就是说双端队列是队列和栈的集合,通过规则来灵活的实现队列和栈的功能。


下面还是先贴出来GLib Reference Manual网址

http://web.mit.edu/barnowl/share/gtk-doc/html/glib/glib-Double-ended-Queues.html#g-queue-copy


GQueue结构体及其相关函数提供了一个标准的队列数据结构。在内部,GQueue使用和glist相同的数据结构来存储元素。可以存储一个int型的数据,或者使用类型转换宏 Type Conversion Macros,去转换成任何数据类型的指针。

创建一个队列使用g_queue_new()

初始化一个静态的队列使用G_QUEUE_INIT 或者 g_queue_init()


这里就涉及到new和init的区别了,在操作系统中,通过动态申请内存,分配在堆上的使用new实现,分配在栈上的使用init实现。在编程的区别就是new的方法可以在程序中动态实现,init在编译之前就已经知道在哪里了。


添加元素使用 g_queue_push_head()g_queue_push_head_link()g_queue_push_tail() 和 g_queue_push_tail_link()

删除元素使用  g_queue_pop_head() 和 g_queue_pop_tail()

释放全部队列使用  g_queue_free()


下面看一下结构体

GQueue

typedef struct {  GList *head;  GList *tail;  guint  length;} GQueue;

head指向队列的第一个元素

tail指向队列的最后一个元素

length是队列的元素个数


下面是队列提供的函数


Synopsis

#include <glib.h>                    GQueue;GQueue*             g_queue_new                         (void);void                g_queue_free                        (GQueue *queue);#define             G_QUEUE_INITvoid                g_queue_init                        (GQueue *queue);void                g_queue_clear                       (GQueue *queue);gboolean            g_queue_is_empty                    (GQueue *queue);guint               g_queue_get_length                  (GQueue *queue);void                g_queue_reverse                     (GQueue *queue);GQueue*             g_queue_copy                        (GQueue *queue);void                g_queue_foreach                     (GQueue *queue,                                                         GFunc func,                                                         gpointer user_data);GList*              g_queue_find                        (GQueue *queue,                                                         gconstpointer data);GList*              g_queue_find_custom                 (GQueue *queue,                                                         gconstpointer data,                                                         GCompareFunc func);void                g_queue_sort                        (GQueue *queue,                                                         GCompareDataFunc compare_func,                                                         gpointer user_data);void                g_queue_push_head                   (GQueue *queue,                                                         gpointer data);void                g_queue_push_tail                   (GQueue *queue,                                                         gpointer data);void                g_queue_push_nth                    (GQueue *queue,                                                         gpointer data,                                                         gint n);gpointer            g_queue_pop_head                    (GQueue *queue);gpointer            g_queue_pop_tail                    (GQueue *queue);gpointer            g_queue_pop_nth                     (GQueue *queue,                                                         guint n);gpointer            g_queue_peek_head                   (GQueue *queue);gpointer            g_queue_peek_tail                   (GQueue *queue);gpointer            g_queue_peek_nth                    (GQueue *queue,                                                         guint n);gint                g_queue_index                       (GQueue *queue,                                                         gconstpointer data);void                g_queue_remove                      (GQueue *queue,                                                         gconstpointer data);void                g_queue_remove_all                  (GQueue *queue,                                                         gconstpointer data);void                g_queue_insert_before               (GQueue *queue,                                                         GList *sibling,                                                         gpointer data);void                g_queue_insert_after                (GQueue *queue,                                                         GList *sibling,                                                         gpointer data);void                g_queue_insert_sorted               (GQueue *queue,                                                         gpointer data,                                                         GCompareDataFunc func,                                                         gpointer user_data);void                g_queue_push_head_link              (GQueue *queue,                                                         GList *link_);void                g_queue_push_tail_link              (GQueue *queue,                                                         GList *link_);void                g_queue_push_nth_link               (GQueue *queue,                                                         gint n,                                                         GList *link_);GList*              g_queue_pop_head_link               (GQueue *queue);GList*              g_queue_pop_tail_link               (GQueue *queue);GList*              g_queue_pop_nth_link                (GQueue *queue,                                                         guint n);GList*              g_queue_peek_head_link              (GQueue *queue);GList*              g_queue_peek_tail_link              (GQueue *queue);GList*              g_queue_peek_nth_link               (GQueue *queue,                                                         guint n);gint                g_queue_link_index                  (GQueue *queue,                                                         GList *link_);void                g_queue_unlink                      (GQueue *queue,                                                         GList *link_);void                g_queue_delete_link                 (GQueue *queue,                                                         GList *link_);

下面提供一段测试代码,


#include <stdio.h>#include <glib.h>//#include <glib/gprintf.h>struct map {    int key;    char *value;} m[10] = {    {0,"zero"},    {1,"one"},    {2,"two"},    {3,"three"},    {4,"four"},    {5,"five"},    {6,"six"},    {7,"seven"},    {8,"eight"},    {9,"nine"},};typedef struct map map;static voidmyPrintInt(gpointer p1, gpointer fmt){    g_printf(fmt, *(gint *)p1);}static voidmyPrintStr(gpointer p1, gpointer fmt){    g_printf(fmt, (gchar *)p1);}static voidtest_queue_1(void){// GQueue* g_queue_new(void);   创建队列    GQueue *queue = g_queue_new();// gboolean g_queue_is_empty(GQueue *queue);    判断队列是否为空,空返回1    gboolean b = g_queue_is_empty(queue);    g_printf("The queue should be empty now.\t\tResult: %s.\n", b ? "YES" : "NO");// void g_queue_push_tail(GQueue *queue, gpointer data);    将数据data压入队列尾部    gint i;    for (i = 0; i < sizeof (m) / sizeof (m[0]); i++)        g_queue_push_tail(queue, m[i].value);    // void g_queue_foreach(GQueue *queue, GFunc func, gpointer user_data);     调用函数func遍历队列元素,user_data是函数的参数    g_printf("Now the queue[after push tail] :\n");    g_queue_foreach(queue, myPrintStr, "%s, ");//打印字符串的形式输出队列的数据,因为之前是将map中的value,即字符串数据保存到了队列中    g_printf("\n");// guint g_queue_get_length(GQueue *queue);     得到队列元素的个数    g_printf("The lenght should be '%d' now.\t\tResult: %d.\n", 10, g_queue_get_length(queue));// void g_queue_reverse(GQueue *queue);     翻转队列的元素    g_queue_reverse(queue);    g_printf("Now the queue[after reverse] :\n");    g_queue_foreach(queue, myPrintStr, "%s, ");    g_printf("\n");// gpointer g_queue_pop_head(GQueue *queue);    从头部取出一个数据    g_printf("The head should be '%s' now.\t\tResult: %s.\n", "nine", (gchar *)g_queue_pop_head(queue));// gpointer g_queue_pop_tail(GQueue *queue);    从尾部取出一个数据    g_printf("The tail should be '%s' now.\t\tResult: %s.\n", "zero", (gchar *)g_queue_pop_tail(queue));    g_printf("Now the queue[after pop head and tail] :\n");    g_queue_foreach(queue, myPrintStr, "%s, ");    g_printf("\n");// gpointer g_queue_pop_nth(GQueue *queue, guint n);    将第n个数据取出    g_printf("The head should be '%s' now.\t\tResult: %s.\n", "eight", (gchar *)g_queue_pop_nth(queue, 0));// void g_queue_push_head(GQueue *queue, gpointer data);    将数据data压入队列头    g_queue_push_head(queue, "zero");    g_queue_push_head(queue, "eight");// void g_queue_push_nth(GQueue *queue, gpointer data, gint n);     将data插入第n个位置    g_queue_push_nth(queue, "nine", 2);    g_printf("Now the queue[after push 'zero' 'eight' 'nine'] :\n");    g_queue_foreach(queue, myPrintStr, "%s, ");    g_printf("\n");// gpointer g_queue_peek_head(GQueue *queue);       查看头数据,不取出    g_printf("The head should be '%s' now.\t\tResult: %s.\n", "eight", (gchar *)g_queue_peek_head(queue));// gpointer g_queue_peek_tail(GQueue *queue);       查看尾数据,不取出    g_printf("The tail should be '%s' now.\t\tResult: %s.\n", "one", (gchar *)g_queue_peek_tail(queue));// gpointer g_queue_peek_nth(GQueue *queue, guint n);   查看第n个数据,不取出    g_printf("The head should be '%s' now.\t\tResult: %s.\n", "eight", (gchar *)g_queue_peek_nth(queue, 0));/*// void g_queue_clear(GQueue *queue);   清理队列,如果数据是动态申请的, 在调用这个函数之前需要先释放数据,这个函数是与init配套使用的,new配套使用free    g_queue_clear(queue);    g_printf("Now the queue[after clear] :\n");    g_queue_foreach(queue, myPrintStr, "%s, ");    g_printf("\n");*/// void g_queue_free(GQueue *queue);    释放队列    g_queue_free(queue);}static gintsort(gconstpointer p1, gconstpointer p2, gpointer user_data)//正向排序规则{    gint32 a, b;        a = *(gint*)(p1);    b = *(gint*)(p2);    return (a > b ? +1 : a == b ? 0 : -1);}static gintmyCompareInt(gconstpointer p1, gconstpointer p2)//比较大小{    const int *a = p1;    const int *b = p2;    return *a - *b;}static gintsort_r(gconstpointer p1, gconstpointer p2, gpointer user_data)//逆向排序规则{    gint32 a, b;        a = *(gint*)(p1);    b = *(gint*)(p2);    return (a < b ? +1 : a == b ? 0 : -1);}static voidtest_queue_2(void){    GQueue *queue = NULL;/*// void g_queue_init(GQueue *queue);    在栈中申请队列    g_queue_init(queue);*/    queue = g_queue_new();// void g_queue_insert_sorted(GQueue *queue, gpointer data, GCompareDataFunc func gpointer user_data);  按照func规则进行插入队列    gint i;    for (i = 0; i < sizeof (m) / sizeof (m[0]); i++)        g_queue_insert_sorted(queue, &m[i].key, sort_r, NULL);    g_printf("Now the queue[after insert sorted] :\n");    for (i = 0; i < queue->length; i++)        g_printf("%d, ", *(gint *)g_queue_peek_nth(queue, i));    g_printf("\n");// void g_queue_remove(GQueue *queue, gconstpointer data);      将队列中的data数据移除,只移除第一次出现的数据    g_queue_remove(queue, &m[3].key);    g_printf("Now the queue[after remove '%d'] :\n", m[3].key);    for (i = 0; i < queue->length; i++)        g_printf("%d, ", *(gint *)g_queue_peek_nth(queue, i));    g_printf("\n");// GList* g_queue_find_custom(GQueue *queue, gconstpointer data, GCompareFunc func);    通过比较函数func查找数据data// void g_queue_insert_before(GQueue *queue, GList *sibling, gpointer data);            将数据data插入到sibling前面// void g_queue_insert_after(GQueue *queue, GList *sibling, gpointer data);             将数据data插入到sibling后面    g_queue_insert_before(queue, g_queue_find_custom(queue, &m[5].key, myCompareInt), &m[3].key);    g_queue_insert_after(queue, g_queue_find_custom(queue, &m[5].key, myCompareInt), &m[3].key);    g_printf("Now the queue[after insert '%d' around '%d'] :\n", m[3].key, m[5].key);    g_queue_foreach(queue, myPrintInt, "%d, ");    g_printf("\n");// void g_queue_sort(GQueue *queue, GCompareDataFunc compare, gpointer user_data);  通过比较函数compare进行排序    g_queue_sort(queue, sort, NULL);    g_printf("Now the queue[sorted] :\n");    g_queue_foreach(queue, myPrintInt, "%d, ");    g_printf("\n");// GQueue* g_queue_copy(GQueue *queue);     复制队列,同样,也只是指针的复制,并没有实际复制数据    GQueue *q = g_queue_copy(queue);    g_printf("Now the queue[copy] :\n");    g_queue_foreach(q, myPrintInt, "%d, ");    g_printf("\n");// void g_queue_remove_all(GQueue *queue, gconstpointer data);      删除队列中所有的data数据    g_queue_remove_all(q, &m[3].key);    g_printf("Now the queue[remove '%d'] :\n", m[3].key);    g_queue_foreach(q, myPrintInt, "%d, ");    g_printf("\n");    g_queue_free(q);    g_queue_free(queue);}intmain(void){    printf("BEGIN:\n************************************************************\n");    printf("\n------------------------------------------------------------\ntest_queue_1:\n");    test_queue_1();    printf("------------------------------------------------------------\n");    printf("\n------------------------------------------------------------\ntest_queue_2:\n");    test_queue_2();    printf("------------------------------------------------------------\n");    printf("\n************************************************************\nDONE\n");    return 0;}


运行结果:


linux@ubuntu:~/16021/glibdemo$ gcc -o Double_ended_Queues Double_ended_Queues.c -lglib-2.0Double_ended_Queues.c: In function ‘test_queue_2’:Double_ended_Queues.c:183:17: warning: initialization makes pointer from integer without a cast [enabled by default]linux@ubuntu:~/16021/glibdemo$ ./Double_ended_Queues BEGIN:************************************************************------------------------------------------------------------test_queue_1:The queue should be empty now.Result: YES.Now the queue[after push tail] :zero, one, two, three, four, five, six, seven, eight, nine, The lenght should be '10' now.Result: 10.Now the queue[after reverse] :nine, eight, seven, six, five, four, three, two, one, zero, The head should be 'nine' now.Result: nine.The tail should be 'zero' now.Result: zero.Now the queue[after pop head and tail] :eight, seven, six, five, four, three, two, one, The head should be 'eight' now.Result: eight.Now the queue[after push 'zero' 'eight' 'nine'] :eight, zero, nine, seven, six, five, four, three, two, one, The head should be 'eight' now.Result: eight.The tail should be 'one' now.Result: one.The head should be 'eight' now.Result: eight.------------------------------------------------------------------------------------------------------------------------test_queue_2:Now the queue[after insert sorted] :9, 8, 7, 6, 5, 4, 3, 2, 1, 0, Now the queue[after remove '3'] :9, 8, 7, 6, 5, 4, 2, 1, 0, Now the queue[after insert '3' around '5'] :9, 8, 7, 6, 3, 5, 3, 4, 2, 1, 0, Now the queue[sorted] :0, 1, 2, 3, 3, 4, 5, 6, 7, 8, 9, Now the queue[copy] :0, 1, 2, 3, 3, 4, 5, 6, 7, 8, 9, Now the queue[remove '3'] :0, 1, 2, 4, 5, 6, 7, 8, 9, ------------------------------------------------------------************************************************************DONElinux@ubuntu:~/16021/glibdemo$ 


好了,常用的函数基本就这些,明天按照顺序应该是序列,但是序列往往用在数据库的主键上,而每个数据库有没有统一的规则,所以应用并不多,暂时先不进行研究,顺序进行hash的研究。


0 0
原创粉丝点击