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的研究。
- Glib学习(3) 双端队列 Double-ended Queues
- C++ Double Ended Queues(双向队列)
- C++ deque(double-ended-queue)双端队列
- 双端队列(Double-ended Queue)
- light oj 1212 - Double Ended Queue (双向队列)
- C++ Queues(队列)
- Lightoj1212——Double Ended Queue(STL)
- RabbitMQ (消息队列)专题学习03 Work Queues(工作队列)
- Glib实例学习(3)哈希表
- GLib学习笔记(3)
- GLib学习笔记(3)
- 标准模板库(STL)学习探究之Double Ended Queue容器
- 标准模板库(STL)学习探究之Double Ended Queue容器
- 第二部分:工作队列(Work queues)
- LeetCode学习之-225. 利用队列实现堆栈(Implement Stack using Queues)
- 数据结构之 链表-Double-Ended List(2)
- 双端堆/最小-最大堆/Double-Ended Heap ?
- STL中的deque介绍--- double-ended queue
- 如何使用php文件测试mongodb是否安装成功
- latex 与 Mathtype使用问题集锦(不断充实中....)
- spark第一个简单示例的源码解读
- 01_JSP 教程
- ssh整合
- Glib学习(3) 双端队列 Double-ended Queues
- 02_JSP 简介
- java Android SDK安装与环境变量配置以及开发第一个Android程序
- 自定义 RadioButton 选中和未选中时的图片
- C日记——泛型的使用
- java 日志异常格式化字符串
- 6.2文件的逻辑结构
- C++走向远洋——46(教师兼干部类、多重继承、派生)
- 深度解析c语言中的关键字