一个通用纯C队列的实现

队列并不是很复杂的数据结构,但是非常实用,这里实现一个队列是因为在我的另一篇博客非常精简的Linux线程池实现中要用到。

队列API定义如下:

//queue.h

#ifndef QUEUE_H_INCLUDED
#define QUEUE_H_INCLUDED

typedef struct queue *queue_t;

queue_t queue_create();

int queue_isempty(queue_t q);

void* queue_enqueue(queue_t q, unsigned int bytes);

void* queue_dequeue(queue_t q);

void queue_destroy(queue_t q);

#endif	//QUEUE_H_INCLUDED
队列API提供的功能有:创建队列,判断队列是否为空,入队,出队,销毁队列。这个队列是通用的,不针对特定数据类型,它里面存储的元素是void*类型的指针。注意这个队列跟普通队列的入队操作有所不同。普通队列的入队操作通常如下:

struct type *p;
p = malloc(sizeof(struct type));
p->a = ...;
p->b = ...;
p->c = ...;
...
queue_enqueue(q, p);
而这里的入队操作简化了流程:

struct type *p;
p=queue_enqueue(q, sizeof(struct type));
p->a = ...;
p->b = ...;
p->c = ...;
...
另外虽然队列元素(指针)所指向的内存空间是在入队操作时由队列分配的,但是队列元素出队以后,队列并不负责元素所指向内存空间的释放,队列使用者应该自己手动释放内存。

队列的实现如下:

//queue.c

#include "queue.h"
#include <stdlib.h>

struct node {
	void *element;
	struct node *next;
};

struct queue {
	struct node front;
	struct node *tail;
};

queue_t queue_create() {
	queue_t q;
	q=(queue_t)malloc(sizeof(struct queue));
	q->front.element=NULL;
	q->front.next=NULL;
	q->tail=&q->front;
	return q;
}

int queue_isempty(queue_t q) {
	return &q->front==q->tail;
}

void* queue_enqueue(queue_t q, unsigned int bytes) {
	q->tail->next=(struct node*)malloc(sizeof(struct node));
	q->tail->next->element=malloc(bytes);
	q->tail->next->next=NULL;
	q->tail=q->tail->next;
	return q->tail->element;
}

void* queue_dequeue(queue_t q) {
	struct node *tmp=q->front.next;
	void *element;
	if(tmp==NULL) {
		return NULL;
	}
	element=tmp->element;
	q->front.next=tmp->next;
	free(tmp);
	if(q->front.next==NULL) {
		q->tail=&q->front;
	}
	return element;
}

void queue_destroy(queue_t q) {
	struct node *tmp, *p=q->front.next;
	while(p!=NULL) {
		tmp=p;
		p=p->next;
		free(tmp);
	}
	free(q); // 感谢@Toudsour指正
}
应用程序使用队列时只需要包含queue.h头文件,并在编译时将queue.c一起编译就行了。因为队列的声明和实现是严格分离的,包含queue.h的应用程序无法也不应该通过队列指针直接访问队列结构体的成员。

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
实现思路: 队列和栈都是一种数据结构队列是先进先出(FIFO),而栈是后进先出(LIFO)。因此,我们可以用一个队列实现栈。 具体实现方法是:栈的入栈操作相当于队列的入队操作,栈的出栈操作相当于队列的出队操作。但是,为了满足栈的后进先出的特点,我们需要在入栈时,将元素插入队列的队头。这样,在出栈时,我们就可以先取出队头的元素,即栈顶元素。 代码实现: ```c #include <stdio.h> #include <stdlib.h> typedef struct Queue { int* data; // 数据存储区 int head; // 队首指针 int tail; // 队尾指针 int size; // 队列大小 } Queue; Queue* create(int size) { Queue* queue = (Queue*) malloc(sizeof(Queue)); queue->data = (int*) malloc(sizeof(int) * size); queue->head = 0; queue->tail = 0; queue->size = size; return queue; } void enqueue(Queue* queue, int value) { if ((queue->tail + 1) % queue->size == queue->head) { printf("Queue is full.\n"); return; } queue->data[queue->tail] = value; queue->tail = (queue->tail + 1) % queue->size; } int dequeue(Queue* queue) { if (queue->head == queue->tail) { printf("Queue is empty.\n"); return -1; } int value = queue->data[queue->head]; queue->head = (queue->head + 1) % queue->size; return value; } typedef struct Stack { Queue* queue; // 队列指针 } Stack; Stack* createStack(int size) { Stack* stack = (Stack*) malloc(sizeof(Stack)); stack->queue = create(size); return stack; } void push(Stack* stack, int value) { enqueue(stack->queue, value); // 将新入栈的元素移到队首 for (int i = 0; i < stack->queue->tail - stack->queue->head - 1; i++) { int value = dequeue(stack->queue); enqueue(stack->queue, value); } } int pop(Stack* stack) { return dequeue(stack->queue); } int main() { Stack* stack = createStack(5); push(stack, 1); push(stack, 2); push(stack, 3); printf("%d\n", pop(stack)); // 3 printf("%d\n", pop(stack)); // 2 push(stack, 4); push(stack, 5); printf("%d\n", pop(stack)); // 5 printf("%d\n", pop(stack)); // 4 printf("%d\n", pop(stack)); // 1 return 0; } ``` 在这个实现中,我们用一个队列实现了栈的基本操作。当需要入栈时,将元素插入队列的队头,然后将队列中所有元素依次出队并入队,使得新插入的元素成为队列的队首元素。出栈时,直接出队即可。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值