GLib 堆栈数据类型?
GLib stack data type?
GLib 是否有可以用作后进先出(堆栈)集合的数据类型?
It does have 列表、队列、哈希表等,但我似乎找不到堆栈数据类型。
有一个垃圾堆栈类型,但它是为特定目的而设计的,并且自 2.48 版以来也已弃用。
在 GLib 中什么可以用作堆栈?
从未使用过,但从文档中您应该可以使用双端队列。要放入堆栈使用 g_queue_push_head()
并从堆栈弹出使用 g_queue_pop_head()
参见:https://people.gnome.org/~desrt/glib-docs/glib-Double-ended-Queues.html
我需要同样的东西,所以我写了这个简单的例子:
// An example stack in glib using a Queue. As this example uses
// integers, we make use of the glib GPOINTER_TO_UINT macros.
//
// Compile by:
// cc `pkg-config --cflags --libs glib-2.0` -o test-stack test-stack.c
#include <glib.h>
#include <stdio.h>
#include <stdint.h>
void pintqueue(GQueue *q)
{
int i;
printf("[%d] ", q->length);
GList *h = q->head;
for (i=0; i<q->length; i++) {
printf("%d ", (int)GPOINTER_TO_UINT(h->data));
h=h->next;
}
printf("\n");
}
void qintpush(GQueue *q, gint val)
{
g_queue_push_tail(q, GUINT_TO_POINTER((guint)val));
}
gint qintpop(GQueue *q)
{
if (q->length==0) {
// "Error handling"
g_message("Ooops! Trying to pop from an empty stack!");
return INT_MAX;
}
return (gint)(GPOINTER_TO_UINT(g_queue_pop_tail(q)));
}
gint main(int argc, char **argv)
{
GQueue q = G_QUEUE_INIT;
qintpush(&q, 34);
qintpush(&q, 42);
qintpush(&q, -1);
pintqueue(&q);
printf("Popped: %d\n", qintpop(&q));
pintqueue(&q);
for (int i=0; i<5; i++)
printf("Popped: %d\n", qintpop(&q));
exit(0);
}
派对有点晚了,但更 light-weight 的堆栈方法是使用 singly-linked 列表类型 GSList,它不需要显式容器对象。
GSList *stack = NULL;
// push:
stack = g_slist_prepend(stack, element);
// stack non-empty?
if (stack) { ... }
// peek head without popping:
element = stack->data;
// pop:
stack = g_slist_delete_link(stack, stack);
一个适当的“pop”包装函数,returns 元素看起来像这样:
void *stack_pop(GSList **stackp) {
if (!*stackp)
return;
void *ret = (*stackp)->data;
*stackp = g_slist_delete_link(*stackp, *stackp);
return ret;
}
// ...
element = stack_pop(&stack); // returns NULL if stack is empty
GLib 是否有可以用作后进先出(堆栈)集合的数据类型? It does have 列表、队列、哈希表等,但我似乎找不到堆栈数据类型。
有一个垃圾堆栈类型,但它是为特定目的而设计的,并且自 2.48 版以来也已弃用。
在 GLib 中什么可以用作堆栈?
从未使用过,但从文档中您应该可以使用双端队列。要放入堆栈使用 g_queue_push_head()
并从堆栈弹出使用 g_queue_pop_head()
参见:https://people.gnome.org/~desrt/glib-docs/glib-Double-ended-Queues.html
我需要同样的东西,所以我写了这个简单的例子:
// An example stack in glib using a Queue. As this example uses
// integers, we make use of the glib GPOINTER_TO_UINT macros.
//
// Compile by:
// cc `pkg-config --cflags --libs glib-2.0` -o test-stack test-stack.c
#include <glib.h>
#include <stdio.h>
#include <stdint.h>
void pintqueue(GQueue *q)
{
int i;
printf("[%d] ", q->length);
GList *h = q->head;
for (i=0; i<q->length; i++) {
printf("%d ", (int)GPOINTER_TO_UINT(h->data));
h=h->next;
}
printf("\n");
}
void qintpush(GQueue *q, gint val)
{
g_queue_push_tail(q, GUINT_TO_POINTER((guint)val));
}
gint qintpop(GQueue *q)
{
if (q->length==0) {
// "Error handling"
g_message("Ooops! Trying to pop from an empty stack!");
return INT_MAX;
}
return (gint)(GPOINTER_TO_UINT(g_queue_pop_tail(q)));
}
gint main(int argc, char **argv)
{
GQueue q = G_QUEUE_INIT;
qintpush(&q, 34);
qintpush(&q, 42);
qintpush(&q, -1);
pintqueue(&q);
printf("Popped: %d\n", qintpop(&q));
pintqueue(&q);
for (int i=0; i<5; i++)
printf("Popped: %d\n", qintpop(&q));
exit(0);
}
派对有点晚了,但更 light-weight 的堆栈方法是使用 singly-linked 列表类型 GSList,它不需要显式容器对象。
GSList *stack = NULL;
// push:
stack = g_slist_prepend(stack, element);
// stack non-empty?
if (stack) { ... }
// peek head without popping:
element = stack->data;
// pop:
stack = g_slist_delete_link(stack, stack);
一个适当的“pop”包装函数,returns 元素看起来像这样:
void *stack_pop(GSList **stackp) {
if (!*stackp)
return;
void *ret = (*stackp)->data;
*stackp = g_slist_delete_link(*stackp, *stackp);
return ret;
}
// ...
element = stack_pop(&stack); // returns NULL if stack is empty