一.概念
和栈相反,队列是一种先进先出(first in first out = FIFO)
的结构。FIFO是单片机的FIFO吗?它是一种线性表,只允许在表的一端插入元素,另一端删除元素。在队列中,能插入的一端叫队尾
,允许删除的一端叫队头
。
二.原理实现
1.节点
因为我们队列还是一种线性表,所以我们的队列的节点因该还是由两个部分构成:数据区
和指向下一个节点的指针
。
2.队列
如果要实现一个队列,我们只需要两个指针并指向它的队头和队尾
就可以了。
它最好使用链式储存,因为它的队头
会经常改变,如果采用顺序结构,可能会浪费空间或者频繁修改大量元素。
在初始化的时候,我们可以把队头队尾
都指向同一个节点,且节点的指向的下一个节点为NULL
。
3.入队
对于入队,我们只需要将元素插入到队尾的后面,再把队尾指向它即可。
4.出队
保存队头指向的下一个节点的地址,记为地址A,把队头指向地址A的下一个节点,然后再free
掉A就可以了。
5.销毁
销毁一个队列,只需要从队头开始,依次把所有的节点free
掉
三.代码
#include <stdio.h>
#include <stdlib.h>
#define OK 1
#define ERROR 0
typedef struct dataType{
int data;
}dataType;
typedef struct nodeType{
dataType data;
struct nodeType *next;
}nodeType;
typedef struct queue{
nodeType *head;
nodeType *tail;
}queue;
queue* QueueInit(void);
int QueuePush(queue* q, dataType data);
int QueueGet(queue* q, dataType *datain);
int QueuePop(queue* q);
int QueueDistroy(queue *q);
int main()
{
// 主函数内容随便改
queue *Q = QueueInit();
dataType test;
int i = 0;
for (i = 0; i < 5; ++i)
{
test.data = i;
QueuePush(Q, test);
}
while(Q->head != Q->tail)
{
QueueGet(Q, &test);
printf("%d\n", test.data);
QueuePop(Q);
}
for (i = 5; i >= 0; --i)
{
test.data = i;
QueuePush(Q, test);
}
while(Q->head != Q->tail)
{
QueueGet(Q, &test);
printf("%d\n", test.data);
QueuePop(Q);
}
return 0;
}
queue* QueueInit(void)
{
queue* q = (queue*)malloc(sizeof(queue));
nodeType* qhead = (nodeType*)malloc(sizeof(nodeType));
// 动态生成一个队列和它里面的一个节点
if (q != NULL && qhead != NULL)
{
qhead->next = NULL;
qhead->data.data = -1; //信息初始化
q->head = qhead; // 头尾都指向同一个节点
q->tail = qhead;
return q;
}
exit(0);
}
int QueuePush(queue* q, dataType datain)
{
nodeType *node = (nodeType*)malloc(sizeof(nodeType));
if (node != NULL)
{
node->data = datain; // 更新节点数据
node->next = NULL;
q->tail->next = node; // 更新队列
q->tail = node; // 跟新队尾指针
return OK;
}
return ERROR;
}
int QueueGet(queue* q, dataType *datain)
{
if (q->head != q->tail && q->head->next != NULL)
{
*datain = q->head->next->data; // 获得头指针指向的节点
return OK;
}
return ERROR;
}
int QueuePop(queue *q)
{
nodeType *dnode = NULL;
if(q->head != q->tail && q->head->next != NULL)
{
dnode = q->head;
q->head = q->head->next; // 将头指针指向现在头指针的下一个节点
free(dnode); // 释放空间
return OK;
}
return ERROR;
}
int QueueDistroy(queue* q)
{
nodeType *dnode = NULL;
while(q->head != q->tail) // 只要头不等于尾,队列就还有成员
{
dnode = q->head;
q->head = q->head->next;
free(dnode); // 同理参考Pop
return OK;
}
return ERROR;
}