又有好长一段时间没有更新这个话题了, 今天我们开始来讲解通用queue的实现。
像前面讲解的其他数据结构一样, 我们还是先来回忆一下简单的queue的实现, 我们都知道queue是一种FIFO的数据结构, 就像我们在车站买车票一样的, 排在前面的人先买到车票, 然后出队列。我们先实现一个简单的queue来复习一下利用C语言该怎么写这个数据结构呢? 就规定写一个保存int类型数据的queue吧。
我们先定义出该int类型的queue的基本操作接口, 具体操作接口如下:
struct c_queue;
extern struct c_queue* c_queue_new(void);
extern void c_queue_free(struct c_queue** cq);
extern int c_queue_empty(struct c_queue* self);
extern size_t c_queue_size(struct c_queue* self);
extern int c_queue_push(struct c_queue* self, int data);
extern int c_queue_pop(struct c_queue* self);
extern int c_queue_top(struct c_queue* self);
有了这些操作接口, 那我在实现的时候该怎么做到数据的先进先出呢? 其实也很简单, 我们只需要定义一个简单的链表结构, 就可以很方便的管理我们的数据了, 关键是实现数据的先进先出, 那该怎么实现呢?
我们都知道利用单链表的话, 实现从头插入和从头部删除是很方便的, 这个就很类似stack的原理了, 但是这里queue是要实现从尾部插入。或许有的同学已经想到了, 对, 我们可以使用双向链表。这个方案确实不错, 但是管理一个简单的queue是不是有点费力了呢?
其实也很简单, 我们可以再保留一个单链表的尾指针就行了啊, 这样我们就可以从单链表的尾部插入数据, 而从其头部取出数据了。
在queue的实现文件里面, 我们定义其结构如下:
struct __queue_node {
int _data;
struct __queue_node* _next;
};
struct c_queue {
size_t _size;
struct __queue_node* _head;
struct __queue_node* _tail;
};
有了queue的具体结构, 这个_head用来保存我们链表的头指针, 而_tail用来保存链表的尾指针, 这样就很简单的实现了链表的尾插和头出。
有了这两个结构, 相信实现该queue的各个操作接口就很简单了吧, 那么我该出其具体的实现方法如下:
static inline struct __queue_node* _queue_new_node(int _x) {
struct __queue_node* node = NULL;
size_t size = sizeof(struct __queue_node);
node = (struct __queue_node*)c_malloc(size);
if (NULL != node)
node->_data = _x;
return node;
}
static inline void _queue_clear(struct c_queue* _p) {
struct __queue_node* n = NULL;
if (NULL != _p) {
while (NULL != _p->_head) {
n = _p->_head;
_p->_head = _p->_head->_next;
c_free(n);
}
_p->_size = 0;
}
}
struct c_queue* c_queue_new(void) {
struct c_queue* self = NULL;
size_t size = sizeof(struct c_queue);
self = (struct c_queue*)c_malloc(size);
return self;
}
void c_queue_free(struct c_queue** cq) {
_queue_clear(*cq);
c_free(*cq);
}
int c_queue_empty(struct c_queue* self) {
return (NULL != self ? NULL == self->_head : 0);
}
size_t c_queue_size(struct c_queue* self) {
return (NULL != self ? self->_size : 0);
}
int c_queue_push(struct c_queue* self, int data) {
struct __queue_node* node = _queue_new_node(data);
if (NULL != self) {
if (NULL == self->_head)
self->_head = self->_tail = node;
self->_tail->_next = node;
self->_tail = node;
self->_size++;
return 0;
}
return -1;
}
int c_queue_pop(struct c_queue* self) {
struct __queue_node* node = NULL;
if (NULL != self) {
if (NULL != self->_head) {
node = self->_head;
self->_head = self->_head->_next;
c_free(node);
self->_size--;
}
return 0;
}
return -1;
}
int c_queue_top(struct c_queue* self) {
struct __queue_node* node = NULL;
if (NULL != self)
node = self->_head;
return (NULL != node ? node->_data : -0x7fffffff);
}
好了通过对这个int类型的queue的实现相信大家对queue已经有所了解了吧, 今天就先到这里吧, 下次我们开始正式实现通用的queue操作接口。