一、链式队列
**队列:**一种允许从一端插入数据,另外一端删除数据的线性存储结构称为队列。
把数据插入的这端称为队列的队尾, 数据删除这端称为队列的队头。
插入操作称为入队;删除操作称为出队。

特点: 先进先出、后进后出**(FIFO)**
应用: 数据缓存
链式队列:

基本操作程序代码:
cpp
#include "linkqueue.h"
#include <stdio.h>
#include <stdlib.h>
LQue_t * create_link_queue()
{
LQue_t *pque = malloc(sizeof(LQue_t));
if (NULL == pque)
{
printf("malloc error\n");
return NULL;
}
pque->phead = NULL;
pque->ptail = NULL;
pque->clen = 0;
return pque;
}
int is_empty_link_queue(LQue_t *pque)
{
return NULL == pque->phead;
}
int push_link_queue(LQue_t *pque, Data_t data)
{
Node_t *pnode = malloc(sizeof(Node_t));
if (NULL == pnode)
{
printf("malloc error\n");
return -1;
}
pnode->data = data;
pnode->pnext = NULL;
if (is_empty_link_queue(pque))
{
pque->phead = pnode;
pque->ptail = pnode;
}
else
{
pque->ptail->pnext = pnode;
pque->ptail = pnode;
}
pque->clen++;
return 0;
}
void show_link_queue(LQue_t *pque)
{
Node_t *ptmp = pque->phead;
while (ptmp != NULL)
{
printf("%d ", ptmp->data);
ptmp = ptmp->pnext;
}
printf("\n");
}
int pop_link_queue(LQue_t *pque, Data_t *pdata)
{
if (is_empty_link_queue(pque))
{
return -1;
}
Node_t *pfree = pque->phead;
pque->phead = pfree->pnext;
if (pdata != NULL)
{
*pdata = pfree->data;
}
free(pfree);
if (NULL == pque->phead)
{
pque->ptail = NULL;
}
pque->clen--;
return 0;
}
int get_link_queue_head(LQue_t *pque, Data_t *pdata)
{
if (is_empty_link_queue(pque))
{
return -1;
}
if (pdata != NULL)
{
*pdata = pque->phead->data;
return 0;
}
return -1;
}
void destroy_link_queue(LQue_t *pque)
{
while (!is_empty_link_queue(pque))
{
pop_link_queue(pque, NULL);
}
free(pque);
}
二、循环队列
**循环队列:**使用顺序结构存储队列数据时,为了避免假溢出,使得顺序队列成为一种尾首相接的存储方式。


假溢出: 如下图,普通的顺序队列存在假溢出问题,所以一般使用循环队列。

**循环队列判空:**head == tail

循环队列判满:(tail+1)%len == head

基本操作程序代码:
cpp
#include "seqqueue.h"
#include <stdio.h>
#include <stdlib.h>
SQue_t *create_seq_queue()
{
SQue_t *psq = malloc(sizeof(SQue_t));
if (NULL == psq)
{
printf("malloc error\n");
return NULL;
}
psq->pbase = malloc(SEQ_MAX_LEN*sizeof(Data_t));
if (NULL == psq->pbase)
{
printf("malloc error\n");
return NULL;
}
psq->head = 0;
psq->tail = 0;
return psq;
}
int is_full_seq_queue(SQue_t *psq)
{
return (psq->tail+1)%SEQ_MAX_LEN == psq->head;
}
int is_empty_seq_queue(SQue_t *psq)
{
return psq->head == psq->tail;
}
int push_seq_queue(SQue_t *psq, Data_t data)
{
if (is_full_seq_queue(psq))
{
return -1;
}
psq->pbase[psq->tail] = data;
psq->tail = (psq->tail+1) % SEQ_MAX_LEN;
return 0;
}
void show_seq_queue(SQue_t *psq)
{
int i = 0;
for (i = psq->head; i != psq->tail; i = (i+1)%SEQ_MAX_LEN)
{
printf("%d ", psq->pbase[i]);
}
printf("\n");
}
int pop_seq_queue(SQue_t *psq, Data_t *pdata)
{
if(is_empty_seq_queue(psq))
{
return -1;
}
if (pdata != NULL)
{
*pdata = psq->pbase[psq->head];
}
psq->head = (psq->head + 1)% SEQ_MAX_LEN;
return 0;
}
int get_seq_queue_head(SQue_t *psq, Data_t *pdata)
{
if (is_empty_seq_queue(psq))
{
return -1;
}
if (pdata != NULL)
{
*pdata = psq->pbase[psq->head];
return 0;
}
return -1;
}
void destroy_seq_queue(SQue_t *psq)
{
free(psq->pbase);
free(psq);
}