上一篇实现了栈,底层使用的是数组,但是实现队列的话,数组就不太方便了,因为入队和出队不是在同一个位置进行的。可以想象一下用数组实现队列的话,我们需要定义一个多长的数组呢?所以显然对于一般的队列而言,使用链表来实现一个基本的队列是可行的。实际上也可以用数组来实现队列,请见下一篇“环形队列”。
同样的,实现基本队列需要做两个工作:1.定义队列的节点 2.基本操作接口。关于测试用例,是一个非常简单的接口测试,如果想要找到一个更加切实的场景,可以去寻找一下广度优先搜索的案例,广度优先搜索就需要维护一个数据队列来完成广度优先搜索。
上代码:
myqueue.h
/*用链表实现队列*/
#ifndef MYQUEUE_H
#define MYQUEUE_H
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
typedef int Item_Queue;
#define QUEUESIZE 20
typedef struct Node_Queue {
Item_Queue item;
struct Node* next;
}QueueNode;
typedef struct Queue {
QueueNode* front;
QueueNode* rear;
int items;
}Queue;
/*初始化队列*/
extern void InitQueue(Queue* pq);
/*检查队列已满*/
extern bool QueueIsFull(Queue * pq);
/*检查队列为空*/
extern bool QueueIsEmpty(Queue* pq);
/*队列中节点数目*/
extern int QueueItemCnt(Queue * pq);
/*向队尾添加节点*/
extern bool EnQueue(Queue* pq,Item_Queue item);
/*从队首删除节点*/
extern bool DeQueue(Queue* pq, Item_Queue* item);
/*清空队列*/
extern void ClearQueue(Queue* pq);
/*遍历队列*/
extern void TraverseQueue(Queue* pq, void(*pfun)(Item_Queue* item));
#endif // !MYQUEUE_H
myqueue.c(关于删除队首节点,需要强调一点,一定要记得释放节点资源,别给整内存泄漏了)
#include"myqueue.h"
#include <stdio.h>
/*初始化队列*/
void InitQueue(Queue* pq) {
pq->front = pq->rear = NULL;
pq->items = 0;
}
/*检查队列已满*/
bool QueueIsFull(Queue * pq) {
return pq->items == QUEUESIZE;
}
/*检查队列为空*/
bool QueueIsEmpty(Queue* pq) {
return pq->items == 0;
}
/*队列中节点数目*/
int QueueItemCnt(Queue * pq) {
return pq->items;
}
/*向队尾添加节点*/
bool EnQueue(Queue* pq, Item_Queue item) {
QueueNode *pnew;
if (QueueIsFull(pq)) {
return false;
}
pnew = (QueueNode *)malloc(sizeof(QueueNode));
if (pnew == NULL) {
printf("@liu@ ERROR unable to allocate memary\n");
return false;
}
pnew->item = item;
pnew->next = NULL;
if (QueueIsEmpty(pq)) {
pq->front = pnew;
pq->rear = pnew;
pq->items++;
}else {
pq->rear->next = pnew;
pq->rear = pq->rear->next;
pq->items++;
}
return true;
}
/*从队首删除节点*/
bool DeQueue(Queue* pq, Item_Queue* item) {
QueueNode* pos;
if (QueueIsEmpty(pq)) {
printf("@liu@ERROR tring to dequeue an empty queue\n");
return false;
}
*item = pq->front->item;
pos = pq->front;
pq->front = pq->front->next;
free(pos);
pq->items--;
return true;
}
/*清空队列*/
void ClearQueue(Queue* pq) {
Item_Queue dummy = 0;
while (!QueueIsEmpty(pq))
DeQueue(pq,dummy);
}
/*遍历队列*/
void TraverseQueue(Queue* pq, void(*pfun)(Item_Queue* item)) {
if (QueueIsEmpty(pq)) {
printf("@liu@ ERROR trying to operate empty queue\n");
return false;
}
Queue* pos;
pos = pq;
do {
(*pfun)(pos->front->item);
pos->front = pos->front->next;
} while (pos->front != pos->rear);
}
测试用例:(测试用例没有使用遍历和清空接口,大家可以试一下我写的,因为我也不知道是不是有bug,尝试debug啦~)
main.c
int main()
{
#if QUEUE_TEST
Queue* queueA = (Queue*)malloc(sizeof(Queue));
InitQueue(queueA);
cout << QueueIsFull(queueA) << endl;
cout << QueueIsEmpty(queueA) << endl;
cout << QueueItemCnt(queueA) << endl;
Item_Queue a[] = {1,2,3,8,9,0};
for (int i = 0; i < 6;i++) {
EnQueue(queueA,a[i]);
cout << "push" << a[i]<<" ";
}
Item_Queue tmp;
cout << endl << QueueItemCnt(queueA) << endl;
for (int i = 0; i < 3; i++) {
DeQueue(queueA, &tmp);
cout << "pop" << tmp << " ";
}
cout << endl << QueueItemCnt(queueA) << endl;
#endif
system("pause");
return 0;
}
测试结果: