目录
- 一、基础知识
- 二、数组实现环队
- 2.1 初始化
- 2.2 判断环队是否为空
- 2.3 判断环队是否为满
- 2.4 入队
- 2.5 出队
- 2.6 取队头元素
- 2.7 取队尾元素
- 2.8 销毁环队
- 三、链表实现环队
- 3.1 初始化
- 3.2 判断环队是否为空
- 3.3 判断环队是否为满
- 3.4 入队
- 3.5 出队
- 3.6 取队头元素
- 3.7 取队尾元素
- 3.8 销毁环队
一、基础知识
- 环形队列:是首尾相连的先进后出的数据结构
- 特点:给定空间大小
- 应用:环形队列广泛用于网络数据收发,和不同程序间数据交换(比如内核与应用程序大量交换数据,从硬件接收大量数据)
- 实现:① 数组环队 ② 链表环队
- 一个严重的问题:
(1) 如何判断队为空?(2) 如何判断队为满?答案:(1)front == tail
(2)front == tail
为了区别两个判断条件的重合问题,需要在数组队/链队预留一个空间的位置
(1)front == tail
(2)(tail+1)%5 == front
二、数组实现环队
结构体:
typedef struct CircularQueue
{
int* arry;
int front;
int tail;
int size;//数组大小
}CQueue;
2.1 初始化
//初始化
void CQueueInit(CQueue* cq, int k)
{
assert(cq);
cq->arry = (int*)malloc(sizeof(int) * (k+1));
cq->front = cq->tail = 0;
cq->size = k;
}
2.2 判断环队是否为空
//判断环形队列是否为空
bool CQueueIsEmpty(CQueue* cq)
{
assert(cq);
return cq->front == cq->tail;
}
2.3 判断环队是否为满
//判断环形队列是否为满
bool CQueueIsFull(CQueue* cq)
{
assert(cq);
return (cq->tail + 1) % (cq->size + 1) == cq->front;
}
2.4 入队
//入队
void CQueuePush(CQueue* cq, int x)
{
assert(cq);
if (CQueueIsFull(cq))
{
printf("队满!");
exit(0);
}
cq->arry[cq->tail] = x;//赋值
cq->tail = (cq->tail + 1) % (cq->size + 1);//tail走一步
}
2.5 出队
//出队
void CQueuePop(CQueue* cq)
{
assert(cq);
if (CQueueIsEmpty(cq))
{
printf("队空!");
exit(0);
}
cq->front = (cq->front + 1) % (cq->size + 1);//front走一步
}
2.6 取队头元素
//取队头元素
int CQueueFront(CQueue* cq)
{
assert(cq);
if (CQueueIsEmpty(cq))
{
printf("队空!");
exit(0);
}
return cq->arry[cq->front];
}
2.7 取队尾元素
//取队尾元素
int CQueueBack(CQueue* cq)
{
assert(cq);
if (CQueueIsEmpty(cq))
{
printf("队空!");
exit(0);
}
int tail_i = (cq->tail + cq->size) % (cq->size + 1);//找到tail的上一个位置
return cq->arry[tail_i];
}
2.8 销毁环队
//环形队列的销毁
void CQueueDestroy(CQueue* cq)
{
assert(cq);
free(cq->arry);
free(cq);
}
“向后走”:
(cur+1)%(k+1)
“向前走”:(cur+k)%(k+1)
三、链表实现环队
结构体:
typedef int DataType;
typedef struct CQueueNode
{
DataType data;
CQueueNode* next;
}CQueueNode;
typedef struct CQueue
{
CQueueNode* front;
CQueueNode* tail;
}CQueue;
3.1 初始化
//初始化
void CQueueInit(CQueue* cq, int k)
{
assert(cq);
CQueueNode* plist = CreatCQueueList(k + 1);
cq->front = cq->tail = plist;
}
//创建k个结点的链表
CQueueNode* CreatCQueueList(int k)
{
CQueueNode* phead = NULL;
CQueueNode* tail = phead;
while (k)
{
CQueueNode* newNode = (CQueueNode*)malloc(sizeof(CQueueNode));
newNode->next = NULL;
if (phead == NULL)
{
phead = tail =newNode;
}
else
{
tail->next = newNode;
tail = newNode;
}
--k;
}
tail->next = phead;
return phead;
}
3.2 判断环队是否为空
//判断环形队列是否为空
bool CQueueIsEmpty(CQueue* cq)
{
assert(cq);
return cq->front == cq->tail;
}
3.3 判断环队是否为满
//判断环形队列是否为满
bool CQueueIsFull(CQueue* cq)
{
assert(cq);
return cq->front == cq->tail->next;
}
3.4 入队
//入队
void CQueuePush(CQueue* cq, int x)
{
assert(cq);
if (CQueueIsFull(cq))
{
printf("队满!");
exit(0);
}
cq->tail->data = x;
cq->tail = cq->tail->next;
}
3.5 出队
//出队
void CQueuePop(CQueue* cq)
{
assert(cq);
if (CQueueIsEmpty(cq))
{
printf("队空!");
exit(0);
}
cq->front = cq->front->next;
}
3.6 取队头元素
//取队头元素
int CQueueFront(CQueue* cq)
{
assert(cq);
if (CQueueIsEmpty(cq))
{
printf("队空!");
exit(0);
}
return cq->front->data;
}
3.7 取队尾元素
//取队尾元素
int CQueueBack(CQueue* cq)
{
assert(cq);
if (CQueueIsEmpty(cq))
{
printf("队空!");
exit(0);
}
CQueueNode* cur = cq->front;
while (cur)
{
if (cur->next == cq->tail)
break;
cur = cur->next;
}
return cur->data;
}
3.8 销毁环队
//环形队列的销毁
void CQueueDestroy(CQueue* cq)
{
assert(cq);
//第一层:free链表结点
CQueueNode* cur = cq->front;
while (cur)
{
CQueueNode* next = cur->next;
free(cur);
cur = next;
}
//第二层:free front和tail
free(cq);
}