循环队列
这里是数据结构个人学习的笔记记录,如有问题欢迎指正说明
一、循环队列
循环队列就好比我们乘坐公交车,当我们上车发现车后面坐满了而前面还有空座的时候,肯定不是说下车等下一俩,而是后面没座了那我就坐前面呗,循环队列解决的就是这样一个问题。因此我们将队列头尾相接的顺序存储结构称为循环队列。
先来定义循环队列的结构,它是顺序存储的结构,因为是循环的所以为了更好的表示,我们增加了头指针和尾指针。具体的定义如下
结构体的定义:
typedef struct CircleIntQueue
{
int data[TOTAL_SPACE];
int head;
int tail;
}*CircleIntQueuePtr;
二、相关操作实现
1.初始化
malloc一个链队列,并生成一个头结点,队头指针和队尾指针为NULL。因为front和rear是我们判断队列为空的条件,所以为了防止队列满时front和rear也相等,我们会让数组中有一个空闲单元。所以判断队列满的条件变为(rear+1)%TOTAL_SPACE==front
CircleIntQueuePtr initQueue()
{
CircleIntQueuePtr resultPtr=(CircleIntQueuePtr)malloc(sizeof(struct CircleIntQueue));
resultPtr->head=0;
resultPtr->tail=0;
return resultPtr;
}
2.依次对栈中的每个数据元素输出
定义一个tempPtr指向队头指针的下一位。
void outputLinkQueue(CircleIntQueuePtr paraPtr)
{
int i;
if(paraPtr->head==paraPtr->tail)
{
printf("Empty queue.");
return ;
}
printf("Element in the queue:");
for(i=paraPtr->head;i<paraPtr->tail;i++)
{
printf("%d ",paraPtr->data[i%TOTAL_SPACE]);
}
printf("\r\n");
}
3.进队列
进队列只能在队尾,所以只需要将队尾指针进行移动。同时不能忘记是循环队列,重点注意下标的变化。
void enqueue(CircleIntQueuePtr paraPtr,int paraValue)
{
if((paraPtr->tail+1)%TOTAL_SPACE==paraPtr->head)
{
printf("Queue full.\r\n");
return ;
}
paraPtr->data[paraPtr->tail%TOTAL_SPACE]=paraValue;
paraPtr->tail++;
}
4.出队列
首先需要判断队列是否为空,如果不为空则将队头元素出队列,并返回该值
int dequeue(CircleIntQueuePtr paraPtr)
{
int resultValue;
if(paraPtr->head==paraPtr->tail)
{
printf("No element in the queue.\r\n");
return -1;
}
resultValue=paraPtr->data[paraPtr->head%TOTAL_SPACE];
paraPtr->head++;
return resultValue;
}
5.链队列中元素个数
遍历整个队列便能得到这个链队列的长度了。
int queuelength(CircleIntQueuePtr paraPtr)
{
int length=0;
for(int i=paraPtr->head;i<paraPtr->tail;i++)
{
length++;
}
return length;
}
6.测试函数
void testLinkQueue()
{
int i=10;
CircleIntQueuePtr tempPtr =initQueue();
for(i;i<16;i++)
{
enqueue(tempPtr,i);
}
outputLinkQueue(tempPtr);
printf("Length of the queue is %d\r\n",queuelength(tempPtr));
for(i=0;i<6;i++)
{
printf("dequeue gets %d\r\n",dequeue(tempPtr));
}
enqueue(tempPtr,8);
outputLinkQueue(tempPtr);
}
7.具体代码实现
#include<stdio.h>
#include<stdlib.h>
#define TOTAL_SPACE 5
typedef struct CircleIntQueue
{
int data[TOTAL_SPACE];
int head;
int tail;
}*CircleIntQueuePtr;
CircleIntQueuePtr initQueue()
{
CircleIntQueuePtr resultPtr=(CircleIntQueuePtr)malloc(sizeof(struct CircleIntQueue));
resultPtr->head=0;
resultPtr->tail=0;
return resultPtr;
}
void enqueue(CircleIntQueuePtr paraPtr,int paraValue)
{
if((paraPtr->tail+1)%TOTAL_SPACE==paraPtr->head)
{
printf("Queue full.\r\n");
return ;
}
paraPtr->data[paraPtr->tail%TOTAL_SPACE]=paraValue;
paraPtr->tail++;
}
int dequeue(CircleIntQueuePtr paraPtr)
{
int resultValue;
if(paraPtr->head==paraPtr->tail)
{
printf("No element in the queue.\r\n");
return -1;
}
resultValue=paraPtr->data[paraPtr->head%TOTAL_SPACE];
paraPtr->head++;
return resultValue;
}
int queuelength(CircleIntQueuePtr paraPtr)
{
int length=0;
for(int i=paraPtr->head;i<paraPtr->tail;i++)
{
length++;
}
return length;
}
void outputLinkQueue(CircleIntQueuePtr paraPtr)
{
int i;
if(paraPtr->head==paraPtr->tail)
{
printf("Empty queue.");
return ;
}
printf("Element in the queue:");
for(i=paraPtr->head;i<paraPtr->tail;i++)
{
printf("%d ",paraPtr->data[i%TOTAL_SPACE]);
}
printf("\r\n");
}
void testLinkQueue()
{
printf("---Begin!---\r\n");
int i=10;
CircleIntQueuePtr tempPtr =initQueue();
for(i;i<16;i++)
{
enqueue(tempPtr,i);
}
outputLinkQueue(tempPtr);
printf("Length of the queue is %d\r\n",queuelength(tempPtr));
for(i=0;i<6;i++)
{
printf("dequeue gets %d\r\n",dequeue(tempPtr));
}
enqueue(tempPtr,8);
outputLinkQueue(tempPtr);
printf("---End!---\r\n");
}
int main()
{
testLinkQueue();
return 0;
}
三、样例输出
—Begin!— Queue full. Queue full. Element in the queue:10 11 12 13 Length of the queue is 4 dequeue gets 10 dequeue gets 11 dequeue gets 12 dequeue gets 13 No element in the queue. dequeue gets -1 No element in the queue. dequeue gets -1 Element in the queue:8 —End!—
四、写在最后
循环队列相比链队列,它必须是事先申请好空间的,使用期间不释放。从空间上说,循环队列必须是一个固定的长度,所以就有了存储元素个数和空间浪费的问题,而链队列就没有这样的问题,总的来说,在可以确定队列长度最大值的情况下,建议使用循环队列,如果无法预估队列的长度,则用链队列。
|