目录
- 一.队列的概念和结构
- 二.队列头文件实现
- 三.队列具体函数实现
-
- 1.队列的初始化
- 2.队列的销毁
- 3.入队列
- 4.出队列
- 5.返回队列头的数据
- 6.返回队列尾的数据
- 7.队列大小的获取
- 8.判断队列是否为空
一.队列的概念和结构
队列是遵循先进先出原则的线性数据结构,仅可以在队尾插入元素,仅可以在队头删除数据。
队列主要分为顺序队列和链式队列两种结构。
顺序队列一般由数组结构来实现,类似于顺序表的方式实现。需要在空间不足时,及时申请空间。
链表队列一般由链表结构来实现,无需担心空间的浪费。
下面队列将用链表的形式来实现。因为顺序表实现的队列,空间大小不足时,扩容不方便。并且在出队函数中,顺序表实现时需要将头节点后面的所有节点前挪一个位置。效率较低。
二.队列头文件实现
c
typedef int QDataType;
typedef struct QueueNode
{
struct QueueNode *next;
QDataType data;
}QNode;
typedef struct Queue
{
QNode* head;
QNode* tail;
}Queue;
//队列的初始化
void QueueInit(Queue *pq);
//队列的销毁
void QueueDestory(Queue *pq);
//入队列
void QueuePush(Queue*pq,QDataType x);
//出队列
void QueuePop(Queue* pq);
//返回队列头的数据
QDataType QueueFront(Queue* pq);
//返回队列尾的数据
QDataType QueueBack(Queue* pq);
//得出队列的大小
int QueueSize(Queue *pq);
//判断队列是否为空
bool QueueEmpty(Queue *pq);
三.队列具体函数实现
1.队列的初始化
c
void QueueInit(Queue *pq)
{
assert(pq);
pq->head=pq->tail=NULL;
}
上述代码的具体解释:首先排除pq指针为空的情况,否则后续会错误的使用空指针,接下来的初始化就是将头节点和尾节点置为NULL即可。
2.队列的销毁
c
void QueueDestory(Queue *pq)
{
assert(pq);
QNode* cur=pq->head;
while(cur)
{
QNode* next=cur->next;
free(cur);
cur=next;
}
pq->head=pq->tail=NULL;
}
上述代码的具体解释:首先排除pq指针为空情况,防止后续对其错误使用。创建一个临时指针变量保存数据的头节点。当该临时变量不为空时,进入while循环释放cur临时变量的空间,并且让cur指针后移,出while循环之后将phead和tail置为NULL即可。
3.入队列
c
void QueuePush(Queue* pq,QDataType x)
{
assert(pq);
QNode* newnode=(QNode*)malloc(sizeof(QNode));
if(newnode==NULL)
{
printf("malloc fail");
exit(-1);
}
newnode->data=x;
newnode->next=NULL;
if(pq->tail==NULL)
{
pq->head=pq->tail=newnode;
}
else
{
pq->tail->next=newnode;
pq->tail=newnode;
}
}
上述代码的具体解释:首先利用malloc函数申请空间节点,用于存储队列的新数据。当申请的节点为空时打印申请失败的错误信息。申请成功时,先插入对应的数据为随后的入队列做好准备。如果tail指针为空,说明队列是空的,此时只需要将新申请的节点赋值给头和尾节点即可。如果tail指针不为空,说明队列不为空,此时需要将新申请的节点接到尾节点的后面,最后更新尾节点位置即可。
4.出队列
c
void QueuePop(Queue* pq)
{
assert(pq);
assert(pq->head);
if(pq->head->next==NULL)
{
free(pq->head)
pq->head=pq->tail=NULL;
}
else
{
QNode* next=pq->head->next;
free(pq->head);
pq->head=next;
}
}
上述代码的具体解释:当队列只有一个节点时,直接释放该节点,之后将其置为NULL。当队列不是一个节点时,先保存头节点的下一个节点,随后释放头节点,最后将保存的节点更新为新的头节点。
5.返回队列头的数据
c
QDataType QueueFront(Queue* pq)
{
assert(pq);
assert(pq->head);
return pq->head->data;
}
上述代码的具体解释:首先排除pq指针为空的情况,再排除head指针为空的情况,防止队列为空,最后返回头指针的数据即可。
6.返回队列尾的数据
c
QDataType QueueBack(Queue *pq)
{
assert(pq);
assert(pq->head);
return pq->tail->data;
}
上述代码的具体解释:首先排除pq指针为空的情况,再排除head指针为空的情况,防止队列为空,最后返回尾指针的数据即可。
7.队列大小的获取
c
int QueueSize(Queue* pq)
{
assert(pq);
int size=0;
QNode* cur=pq->head;
while(cur)
{
++size;
cur=cur->next;
}
return size;
}
上述代码的具体解释:首先排除pq指针为空的情况,随后创建一个变量用于存储队列的大小。随后创建一个结构体指针变量用于存储头节点。当cur临时指针变量不为NULL时进入循环,size变量在一次一次的循环中不断自增直到cur变量为空。最后返回size的值即可。
8.判断队列是否为空
c
bool QueueEmpty(Queue* pq)
{
assert(pq);
return pq->head==NULL;
}
上述代码的具体解释:返回值为bool类型,先排除pq指针为空的情况,当表达式pq->head为空时,返回真。当表达式为假时,返回假。