循环队列实现(C语言)

 背景:

生活中有很多队列的影子,比如打饭排队,买火车票排队问题等,可以说与时间相关的问题,一般都会涉及到队列问题;从生活中,可以抽象出队列的概念,队列就是一个能够实现“先进先出”的存储结构。队列分为链式队列和静态队列;静态队列一般用数组来实现,但此时的队列必须是循环队列,否则会造成巨大的内存浪费;链式队列是用链表来实现队列的。这里讲的是循环队列。

1、循环队列

循环队列的提出:为充分利用向量空间,克服"假溢出"现象

方法:将向量空间想象为一个首尾相接的圆环,并称这种向量为循环向量。存储在其中的队列称为循环队列(Circular Queue)。存储在其中的队列称为循环队列(Circular Queue

 实现方式这种循环队列可以以单链表的方式来在实际编程应用中来实现     

特点:队列的操作特点先进先出。前者主要是头指针、尾指针的使用,后者主要是理解循环队列提出的原因及其特点。两者都要掌握队列空与满的判定条件以及出队列、入队列操作的实现。

 

2、实现循环队列的注意事项

循环队列中,由于入队时尾指针向前追赶头指针;出队时头指针向前追赶尾指针,造成队空和队满时头尾指针均相等。因此,无法通过条件front==rear来判别队列是""还是""

解决这个问题的方法至少有两种:

  1)另设一变量,用来记录数组中当前元素的个数,以区别队列的空和满;

  2)另一种方式就是数据结构常用的:队满时:(rear+1)%n==frontn为队列长度(所用数组大小),由于rearfront均为所用空间的指针,循环只是逻辑上的循环,所以需要求余运算。如图a情况,队已满,但是rear5+1=6=front0),对空间长度求余,作用就在此6%6=0=front0)。(其二是少用一个元素空间,也就是最后一个存储空间不用,如图1,约定以队列头指针在队列尾指针的下一位置(指环状的下一位置)上作为队列呈状态的标志。当(rear+1%maxsiz=front时,队列满

图a

图1

图2

 3、源码

#ifndef __QUEUE_H_  
#define __QUEUE_H_  

typedef  int QueueElementDataType;



///
//利用空一个元素空间区分队空还是队满
//
typedef struct queue   
{  
	QueueElementDataType *pBase;	  //初始化的动态非配存储空间
	int front;    //队头指针,指向队首位置,删除一个元素就将front顺时针移动一位  
	int rear;    //队尾指针,指向队列最后一个元素的下一个元素,插入一个元素就将rear顺时针移动一位 
	int QueueMaxsize; //循环队列的最大存储空间  
}QUEUE,*PQUEUE;  

void InitialQueue(PQUEUE Q,int QueueMaxsize);   
bool FullQueue(PQUEUE Q);  
bool EmptyQueue(PQUEUE Q);  
bool Enqueue(PQUEUE Q, int val);  
bool Dequeue(PQUEUE Q, int *val);  

///
//利用计数标志区分队空还是队满
//
typedef struct queue2   
{  
	QueueElementDataType *pBase;	  //初始化的动态非配存储空间
	int front;    //队头指针,指向队首位置,删除一个元素就将front顺时针移动一位  
	int rear;    //队尾指针,指向队列最后一个元素的下一个元素,插入一个元素就将rear顺时针移动一位 
	int QueueMaxsize; //循环队列的最大存储空间  
	int nCount;	 //计算器
}QUEUE2,*PQUEUE2;  

void InitialQueue2(PQUEUE2 Q,int QueueMaxsize); 
bool FullQueue2(PQUEUE2 Q);  
bool EmptyQueue2(PQUEUE2 Q); 
bool Enqueue2(PQUEUE2 Q, int val);  
bool Dequeue2(PQUEUE2 Q, int *val);  

#endif

#include "CirculeQueue.h"
#include <stdlib.h>

//队列初始化
void InitialQueue(PQUEUE Q,int QueueMaxsize)
{
	Q->front = Q->rear = 0;	//对头对尾指向同一个存储空间,置队空
	Q->pBase = (int *)malloc(QueueMaxsize * sizeof(QueueElementDataType));//动态申请队列存储空间(对已知队列长度的前提下,用循环队列)
}

//入队
bool Enqueue(PQUEUE Q, int val)  
{  
	if(FullQueue(Q))  
		return false;  
	else  
	{  
		Q->pBase[Q->rear]=val;  
		Q->rear=(Q->rear+1)%Q->QueueMaxsize; 

		return true;  
	}  
} 

//出队
bool Dequeue(PQUEUE Q, int *val)  
{  
	if(EmptyQueue(Q))  
	{  
		return false;  
	}  
	else  
	{  
		*val=Q->pBase[Q->front];  
		Q->front=(Q->front+1)%Q->QueueMaxsize;

		return true;  
	}  
}  

//队列判空
bool EmptyQueue(PQUEUE Q)  
{  
	if(Q->front==Q->rear)    //队空  
		return true;  
	else  
		return false;  
}  

//队列判满
bool FullQueue(PQUEUE Q)  
{  
	if(Q->front==(Q->rear+1)%Q->QueueMaxsize)    //队满,留一个预留空间不用  
		return true;  
	else  
		return false;  
}  


void InitialQueue2(PQUEUE2 Q,int QueueMaxsize)
{
	Q->front = Q->rear;	//对头对尾指向同一个存储空间,置队空
	Q->pBase = (int *)malloc(QueueMaxsize * sizeof(QueueElementDataType));//动态申请队列存储空间(对已知队列长度的前提下,用循环队列)
}

bool EmptyQueue2(PQUEUE2 Q)
{
	if(Q->nCount == 0)	//队空 
		return true;
	else
		return false;
}

bool FullQueue2(PQUEUE2 Q)
{
	if(Q->nCount == Q->QueueMaxsize) //队满
		return true;
	else
		return false;
}

bool Enqueue2(PQUEUE2 Q, int val)
{
	if(EmptyQueue2(Q))  
	{  
		return false;  
	}  
	else  
	{  
		Q->pBase[Q->rear] = val; //新元素插入队尾  每当插入新的队列尾元素时,“尾指针增1”
		Q->rear = (Q->rear + 1)%Q->QueueMaxsize;//队尾指针指向下一个元素
		Q->nCount++; //队列元素个数加1

		return true;  
	} 
}
bool Dequeue2(PQUEUE2 Q, int *val)
{
	if (FullQueue2(Q))
	{
		return false;
	} 
	else
	{
		*val = Q->front;
		Q->front = (Q->front + 1)%Q->QueueMaxsize;//每当删除队列头元素时,“头指针增1”
		Q->nCount--; //队列元素个数减1

		return true;
	}
}

int main()
{
	QUEUE Q;
	Q.QueueMaxsize = 100;//队列长度

	InitialQueue(&Q,100);//初始化队列

	for(int i = 0;i< Q.QueueMaxsize -2;i++)//空一个存储空间
	{
		Enqueue(&Q,i);
	}

	for(int i = 0;i< Q.QueueMaxsize -2;i++)
	{
		Dequeue(&Q,&i);
	}

	//

	QUEUE2 Q2;
	Q2.QueueMaxsize = 100;//队列长度

	InitialQueue2(&Q2,Q2.QueueMaxsize);//初始化队列

	for(int i = 0;i< Q2.QueueMaxsize -1;i++)//装满所有存储空间
	{
		Enqueue2(&Q2,i);
	}

	for(int i = 0;i< Q2.QueueMaxsize -1;i++)
	{
		Dequeue2(&Q2,&i);
	}
	

	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值