代码:
#include <stdio.h>
#include <malloc.h>
#define TOTAL_SPACE 5
typedef struct CircleIntQueue
{
int data[TOTAL_SPACE];
int front;
int rear;
}*CircleIntQueuePtr;
CircleIntQueuePtr initQueue()
{
CircleIntQueuePtr resultPtr = (CircleIntQueuePtr)malloc(sizeof(struct CircleIntQueue));
resultPtr->front = 0;
resultPtr->rear = 0;
return resultPtr;
}
void enqueue(CircleIntQueuePtr paraPtr, int paraValue)
{
printf("Enqueue: %d ", paraValue);
if ((paraPtr->rear + 1) % TOTAL_SPACE == paraPtr->front) {
printf("Queue full.\r\n");
return;
}
paraPtr->data[paraPtr->rear] = paraValue;
paraPtr->rear = (paraPtr->rear + 1) % TOTAL_SPACE;
}
int dequeue(CircleIntQueuePtr paraPtr)
{
int resultValue;
if (paraPtr->front == paraPtr->rear) {
printf("No element in the queue.\r\n");
return -1;
}
resultValue = paraPtr->data[paraPtr->front];
paraPtr->front = (paraPtr->front + 1) % TOTAL_SPACE;
return resultValue;
}
void outputCircleIntQueue(CircleIntQueuePtr paraPtr)
{
int i;
if (paraPtr->front == paraPtr->rear) {
printf("Empty queue.");
return;
}
printf("Elements in the queue: ");
for (i = paraPtr->front; i != paraPtr->rear; i = (i + 1) % TOTAL_SPACE) {
printf("data[%d] = %d, ", i, paraPtr->data[i]);
}
printf("\r\n");
}
void testCircleIntQueue()
{
int i = 10;
CircleIntQueuePtr tempPtr = initQueue();
for (; i < 16; i ++) {
enqueue(tempPtr, i);
}
outputCircleIntQueue(tempPtr);
for (i = 0; i < 6; i ++) {
printf("dequeue gets %d\r\n", dequeue(tempPtr));
}
for (i = 3; i < 6; i ++) {
enqueue(tempPtr, i);
}
for (i = 20; i < 30; i ++) {
enqueue(tempPtr, i);
printf("dequeue gets %d\r\n", dequeue(tempPtr));
outputCircleIntQueue(tempPtr);
}
}
int main()
{
testCircleIntQueue();
return 1;
}
运行结果:
学习心得:
学习C语言中的循环队列(Circular Queue)是一个深入理解队列数据结构以及内存管理的重要过程。循环队列相较于普通队列(如链式队列)在内存使用上更为高效,因为它在固定大小的数组中实现了队列的先入先出(FIFO)特性,避免了内存的动态分配和释放,同时也通过“循环”的特性实现了对队列尾部元素的“环绕”,从而有效地利用了数组的每一个空间。
理解基本结构和原理:
循环队列的核心思想是使用两个指针(front 和 rear)来指示队列的头部和尾部。当队列为空时,front 和 rear 通常指向数组的起始位置;当队列满时,front 和 rear 会在某种条件下相遇(通常是在数组末尾相遇后rear会指向数组的起始位置,形成一个循环)。
判断队列空和满的条件:
在循环队列中,判断队列是否为空或满需要特别注意。常见的判断方法有两种:一种是浪费一个数组空间,当front和rear相等时表示队列为空,当(rear+1)%size == front时表示队列满(其中size是数组的大小);另一种方法是使用额外的变量(如count)来记录队列中元素的个数,但这种方法会增加空间和时间复杂度。
循环操作:
循环队列的“循环”特性体现在对队列尾部元素的环绕处理上。当rear指针指向数组的最后一个元素并需要再次添加元素时,它会自动环绕到数组的起始位置,继续向后移动。这需要对数组的索引进行模运算,以确保指针始终在数组的合法范围内。
内存管理:
循环队列使用固定大小的数组来存储数据,因此不需要像链式队列那样频繁地进行内存分配和释放。这使得循环队列在内存使用上更为高效,同时也降低了因内存管理不当而引发错误的风险。