数据结构-线性表之循环队列

一:循环队列

实现队列要么使用数组,要么使用链表,但由于数组对于出队和入队这样的操作效率不高,所以实现队列一般使用链表。如果现在要求你使用顺序表(也就是顺序队)来实现队列,在不考虑操作的复杂性的情况下肯定是可以实现的,但是这会存在一个致命的问题——“假溢出”。如下,经过一系列入队出队操作,某一刻出现越界。

在这里插入图片描述在这里插入图片描述
一旦出现越界,这个队列就等于“报废”了

而解决这个问题可以用到循环队列,循环队列从感觉上讲不是一个直链,而是一个圆环,在某一刻队满时,此时还要入队的话,队头指针便指向第一个元素,重复利用之前的空间
在这里插入图片描述

对于普通的顺序队,其判断队满的条件为容量满,对于循环队来说,其判断队空和队满的条件有点不同
首先,队空时自然rear=front,也即下图
在这里插入图片描述
而后进队两个元素,进队时arr[rear]=x,然后rear+1如下图
在这里插入图片描述
继续入队,入到不能再入为止,此时rear=front,但是前面队空时也有rear=front
在这里插入图片描述
所以为了区分队空和队满,必须牺牲掉一个元素的位置(图中a8)这也就是为什么在申请空间时需要多申请一个原因。如下当元素到达a7时,即为设定的队满状态。此时front=rear+1
在这里插入图片描述
在这样一个循环队列中,队列空间为8个,下标范围[0-7],当rear=7时队满。如果继续入队,rear就不能直接+1了,否则会越界。而要使得rear从rear=7跳到rear=0,可以rear=(rear+1)%8,因为任何一个数对8取余,其结果都会被映射在[0-7]内。同时为了统一操作,将所有的rear=rear+1均改为rear=(rear+1)%8。

所以说队空rear=front;队满front=(rear+1)%MaxSize;移动指针rear=(rear+1)%MaxSizefront=(front+1)%MaxSize;

二:实现

(1)结构体定义

在这里插入图片描述

(2)初始化

在这里插入图片描述

(3)入队

在这里插入图片描述

(4)出队

在这里插入图片描述

(5)返回队头和队尾

在这里插入图片描述
在这里插入图片描述

三:代码

CircularQueue.h

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

typedef int DataType;

typedef struct CircularQueue
{
    
    
	int _front;
	int _rear;
	DataType* _arr;

}CircularQueue;

void CircularQueueInit(CircularQueue* pq);//初始化
void CircularQueuePush(CircularQueue* pq, DataType x);//入队
void CircularQueuePop(CircularQueue* pq);//删除
DataType CircularQueueHead(CircularQueue* pq);//队头
DataType CircularQueueTail(CircularQueue* pq);//队头

CircularQueue.c

#include "CircularQueue.h"


void CircularQueueInit(CircularQueue* pq)
{
    
    
	pq->_front = 0;
	pq->_rear = 0;
	pq->_arr = (DataType*)malloc(sizeof(DataType)*(8+1));
}

void print(CircularQueue* pq)
{
    
    
	assert(pq);
	int cur = pq->_front;
	while (cur != pq->_rear)
	{
    
    
		printf("%d ", pq->_arr[cur]);
		cur = (cur + 1) % 9;

	}

}

void CircularQueuePush(CircularQueue* pq, DataType x)
{
    
    
	assert(pq);
	if ((pq->_rear + 1) % 9 == pq->_front)
		return;

	pq->_arr[pq->_rear] = x;
	pq->_rear = (pq->_rear + 1) % 9;
}
void CircularQueuePop(CircularQueue* pq)
{
    
    
	assert(pq);
	if (pq->_rear == pq->_front)
		return;
	pq->_front=(pq->_front + 1) % 9;
}
DataType CircularQueueHead(CircularQueue* pq)
{
    
    
	assert(pq);
	if (pq->_rear == pq->_front)
		exit(-1);
	return pq->_arr[pq->_front];

}
DataType CircularQueueTail(CircularQueue* pq)
{
    
    
	assert(pq);
	if (pq->_rear == pq->_front)
		exit(-1);
	else
	{
    
    
		int cur = pq->_front;
		while ((cur + 1) % 9 != pq->_rear)
			cur = cur++;
		return pq->_arr[cur];
	}

}

test.c

#include "CircularQueue.h"


void test()
{
    
    
	CircularQueue CQ;
	CircularQueueInit(&CQ);
	CircularQueuePush(&CQ, 1);
	CircularQueuePush(&CQ, 2);
	CircularQueuePush(&CQ, 3);
	CircularQueuePush(&CQ, 4);
	print(&CQ);
	printf("\n");
	CircularQueuePop(&CQ);
	print(&CQ);
	printf("\n");
	printf("队头元素是%d \n", CircularQueueHead(&CQ));
	printf("队尾元素是%d \n", CircularQueueTail(&CQ));

}
int main()
{
    
    
	test();
}

猜你喜欢

转载自blog.csdn.net/qq_39183034/article/details/113523020