什么是队列:
队列是限定在两端进行插入操作和删除操作的线性表。具有先入先出(FIFO)的特点
相关名词:
循环队列是以数组形式构成的队列数据结构。
循环队列的结构体如下:
typedef int data_t; //队列数据类型
#define N 64 //队列容量
typedef struct{
data_t data[N]; //数据
int front; //队头位置,代表将要出队的位置
int rear; //队尾位置,代表将要入队的位置
}sequeue_t;
入队与出队示意图:
在循环队列中,fornt代表将要出队的位置,rear代表将要入队的位置。
循环队列代码的文件构成:
循环队列相关函数:
创建循环队列就是申请空间,并让入队位置与出队位置相等,这代表队列为空。
具体代码实现如下:
/*
* queue_create:创建队列
* @ret NULL--err other--空队列指针
* */
sequeue* queue_create(void){
sequeue* pQueue = NULL;
//1.申请空间
pQueue = (sequeue*)malloc(sizeof(sequeue));
if(pQueue == NULL){
printf("malloc err\n");
return NULL;
}
//2.初始化,front = rear代表空队列
memset(pQueue->data,0,N*sizeof(data_t));
pQueue->front = 0;
pQueue->rear = 0;
return pQueue;
}
删除就是释放申请的空间即可。
具体代码实现如下:
/*
* queue_del:销毁队列
* param pQueue:要销毁的队列
* @ret -1--err 0--success
* */
int queue_del(sequeue** pQueue){
//1.判断参数有效性
if(*pQueue == NULL){
printf("pQueue is NULL\n");
return -1;
}
free(*pQueue);
*pQueue = NULL;
return 0;
}
入队列的示意图如 "1、基本内容" 中所示,只需要在rear处填入数据并把rear进行偏移即可。
注意:入队列时,需要判断队列是否已满
具体代码实现如下:
/*
* enter_queue:入队列
* param pQueue:要入哪一个队列
* param value:要入队的数据
* @ret -1--err 0--success
* */
int enter_queue(sequeue* pQueue,data_t value){
//1.判断参数有效性
if(pQueue == NULL){
printf("pQueue is NULL\n");
return -1;
}
//2.判断队列是否已满
if( ((pQueue->rear+1)%N) == pQueue->front ){
printf("queue is full\n");
return -1;
}
//3.入队列,就是在rear出写入数据
pQueue->data[pQueue->rear] = value;
pQueue->rear = (pQueue->rear+1)%N;
return 0;
}
出队列的示意图如 "1、基本内容" 中所示,只需要在front处取出数据并把front进行偏移即可。
注意:出队列时,需要判断队列是否为空
具体代码实现如下:
/*
* out_queue:出队列
* param pQueue:要出哪一个队列的数据
* param value:要出队的数据存放的位置
* @ret -1--err 0--success
* */
int out_queue(sequeue* pQueue,data_t* value){
//1.判断参数有效性
if(pQueue == NULL){
printf("pQueue is NULL\n");
return -1;
}
//2.判断队列是否为空
if(pQueue->front == pQueue->rear){
printf("queue is empty\n");
return -1;
}
//3.出队列,就是从front处读数据
*value = pQueue->data[pQueue->front];
pQueue->front = (pQueue->front+1)%N;
return 0;
}
链式队列是以链表形式构成的队列数据结构。
链式队列的结构体如下:
typedef int data_t;
//链表
typedef struct node{
data_t data;
struct node* pNext;
}listnode,*linklist;
//队列
typedef struct{
linklist front;//始终指向冗余的头
linklist reat; //始终指向入队的位置,新数据接在rear后
}linkqueue;
入队与出队示意图:
在链式队列中,fornt代表冗余的头,rear代表将要入队的位置。
链式队列代码的文件构成:
链式队列相关函数:
创建链式队列,需要申请两个空间:冗余的头和队列。初始化时需要把front、rear指向冗余的头,代表这个队列为空队。
具体代码实现如下:
/*
* queue_create:创建一个空队列
* @ret NULL--err other--空队列指针
* */
linkqueue* queue_create(void){
linkqueue* pQueue = NULL;
linklist pLink = NULL;
//1.申请空间
//1.1 队列空间
pQueue = (linkqueue*)malloc(sizeof(linkqueue));
if(pQueue == NULL){
printf("pQueue malloc err\n");
return NULL;
}
//1.2 单链表空间
pLink = (linklist)malloc(sizeof(listnode));
if(pLink == NULL){
printf("pLink malloc err\n");
free(pQueue);//释放前面申请的空间
return NULL;
}
//2.初始化
pLink->data = 0;
pLink->pNext = NULL;
pQueue->front = pLink;
pQueue->rear = pLink;
return pQueue;
}
删除链式队列,首先需要释放单链表的空间,之后再释放队列的空间。
具体代码实现如下:
/*
* queue_delete:删除整个队列
* param pQueue:队列地址
* @ret -1--err 0--success
* */
int queue_delete(linkqueue** pQueue){
linklist pTmp = NULL;
//1.判断参数有效性
if(*pQueue == NULL){
printf("pQueue is NULL\n");
return -1;
}
//2.开始释放链表
while((*pQueue)->front != NULL){
pTmp = (*pQueue)->front;
(*pQueue)->front = (*pQueue)->front->pNext;
free(pTmp);
}
//3.释放队列
free(*pQueue);
*pQueue = NULL;
return 0;
}
入队列的示意图如 "1、基本内容" 中所示,只需要将新数据链接到rear后即可,之后rear需要指向新数据。
具体代码实现如下:
/*
* enter_queue:入队列
* param pQueue:队列地址
* param value:入队数据
* @ret -1--err 0--success
* */
int enter_queue(linkqueue* pQueue,data_t value){
linklist pLink = NULL;
//1.判断参数有效性
if(pQueue == NULL){
printf("pQueue is NULL\n");
return -1;
}
//2.创建链表结点
pLink = (linklist)malloc(sizeof(listnode));
if(pLink == NULL){
printf("malloc err\n");
return -1;
}
pLink->data = value;
pLink->pNext = NULL;
//3.入队列
//rear后链接新结点
pQueue->rear->pNext = pLink;
//队列指针偏移
pQueue->rear = pLink;
return 0;
}
出队列的示意图如 "1、基本内容" 中所示,需要将front后一个数据进行释放,并连接上剩余的数据。
注意点1:当出队列后,队列为空队,这时需要将rear指向冗余的头
注意点2:出队列之前需要先判断队列是否为空
注意点3:出队之后,需要释放出队元素的空间
具体的代码实现如下:
/*
* out_queue:出队列
* param pQueue:队列地址
* param value:出队数据存放的地址
* @ret -1--err 0--success
* */
int out_queue(linkqueue* pQueue,data_t* value){
linklist pTmp = NULL;
//1.判断参数有效性
if(pQueue == NULL){
printf("pQueue is NULL\n");
return -1;
}
//2.判断是否为空队列
if(pQueue->front == pQueue->rear){
printf("queue is empty\n");
return -1;
}
//3.保存剩余数据
pTmp = pQueue->front->pNext->pNext;
//4.出队后队列为空时,需将rear指向冗余头部代表空队列
if(pQueue->front->pNext == pQueue->rear){
pQueue->rear = pQueue->front;
}
//5.开始出队列
*value = pQueue->front->pNext->data;
free(pQueue->front->pNext);
pQueue->front->pNext = pTmp;
return 0;
}