循环队列-数据结构(C语言)

一.循环队列定义

1.队列

在讲循环队列之前先了解一下队列以及队列定义

队列: 

1.队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和一样,队列是一种操作受限制的线性表

2.队列的数据元素又称为队列元素。

3.在队列中插入一个队列元素称为入队,从队列中删除一个队列元素称为出队。

注:队列只允许在一端插入,在另一端删除,所以只有最早进入队列的元素才能最先从队列中删除,故队列又称为先进先出(FIFO—first in first out)线性表

2.定义

 为充分利用向量空间,克服"假溢出"现象的方法是:将向量空间想象为一个首尾相接的圆环,并称这种向量为循环向量。存储在其中的队列称为循环队列(Circular Queue)。循环队列是把顺序队列首尾相连,把存储队列元素的表从逻辑上看成一个环,成为循环队列

3.特点

1.循环队列的头指针(rear)和尾指针(front)可以同时操作,也避免在进行增删元素时移动大量元素,不需要有先后顺序,且先进先出的原则;

2.在基础操作上循环列表可以凭借先进先出,同时在操作中避免了大量元素的移动等优点增加了效率;

二.顺序表的基本操作

1.初始化:建立空的循环队列,rear指针和front指针指向初始位置。

2.入队:插入操作

3.出对:删除操作

4. 队空;使用rear指针和front指针判断中间是否有值

5. 队满:使用rear指针和front指针判断是否=maxsize;

6. 输出队列:将队列中的元素输出

7. 算出队长:计算出循环队列的长度getLenth

8. 找出队头:找出第一个元素

操作演示:

1.初始化

 rear指针和front指针指向初始位置。值均为0.

​
/*循环队列初始化*/
int init(CirclesQueue *Q)
{
	Q->front = Q->rear = 0;
	return 0;
}

​

2.入队

/*入队*/
int enqueue(CirclesQueue *Q, DataType x)
{
	if(isfull(Q))
	{
		printf("队列已满!100001\n");
		return 100001;
	}

	Q->rear = (Q->rear+1) % MAXSIZE;
	Q->data[Q->rear] = x;
	return 0;
}

3.出对

/*出队*/
int dequeue(CirclesQueue *Q, DataType *x)
{
	if(isempty(Q))
	{
		printf("队列为空!100002\n");
		return 100002;
	}
	Q->front = (Q->front+1) % MAXSIZE;
	*x = Q->data[Q->front];
	return 0;
}

4. 队空

利用isempty(CirclesQueue *Q)函数判断队列是否为空。

1.队列的front指针和rear指针相等,那么队列为空,函数返回1;

2.若不为空队 函数返回0。

/*队空*/
int isempty(CirclesQueue *Q)
{
	return (Q->front == Q->rear) ? 1 : 0;
}

5. 队满

利用isfull(CirclesQueue *Q)函数判断队列是否已满。

1.若队列的rear指针加1后对MAXSIZE取模的结果等于front指针,那么队列已满,函数返回1;

2.若队列未满,函数返回0。

/*队满?*/
int isfull(CirclesQueue *Q)
{
	return (Q->rear+1)%MAXSIZE == Q->front ? 1 : 0;
}

6. 输出队列

1.没有值输出“队列为空”

2.如果队列不为空,则初始化一个变量 i,从队列的 front 指针的位置开始。

3.然后,使用 do-while 循环遍历队列。循环继续进行,直到 i 到达队列的 rear 指针的位置

void printQueue(CirclesQueue *Q){
   int i;
   if(isempty(&Q)){
    printf("队列为空\n");
   }
   i = (Q->front) % MAXSIZE;
   do{
      printf("%d",Q->data[(i + 1 % MAXSIZE)]);
	  i = (i + 1) % MAXSIZE;
   }while(i != Q->rear);
}

7. 算出队长

通过计算头指针rear和尾指针front之间的距离来得到。

如果rear指针在front指针的前面,getLength=rear - front + MAXSIZE

% MAXSIZE是为了确保在计算队列长度时不会超出数组的边界。

int getLength(CirclesQueue *Q){
  return(Q->rear - Q->front +MAXSIZE) % MAXSIZE;
}

8. 找出队头

  a.找出第一个元素的位置(Q->front)%MAXSIZE

  b.输出值

/*找出对头*/
DataType getFront(CirclesQueue *Q){
  int i;
  i=(Q->front)%MAXSIZE;
  return  Q->data[(i +1%MAXSIZE)];
}

三.操作截图

四.完整代码

/*
	CirclesQueue.c
*/
#include "CirclesQueue.h"

/*循环队列初始化*/
int init(CirclesQueue *Q)
{
	Q->front = Q->rear = 0;
	return 0;
}


/*入队*/
int enqueue(CirclesQueue *Q, DataType x)
{
	if(isfull(Q))
	{
		printf("队列已满!100001\n");
		return 100001;
	}

	Q->rear = (Q->rear+1) % MAXSIZE;
	Q->data[Q->rear] = x;
	return 0;
}

/*队满?*/
int isfull(CirclesQueue *Q)
{
	return (Q->rear+1)%MAXSIZE == Q->front ? 1 : 0;
}


/*出队*/
int dequeue(CirclesQueue *Q, DataType *x)
{
	if(isempty(Q))
	{
		printf("队列为空!100002\n");
		return 100002;
	}
	Q->front = (Q->front+1) % MAXSIZE;
	*x = Q->data[Q->front];
	return 0;
}

/*队空*/
int isempty(CirclesQueue *Q)
{
	return (Q->front == Q->rear) ? 1 : 0;
}
/*输出队列*/
void printQueue(CirclesQueue *Q){
   int i;
   if(isempty(&Q)){
    printf("队列为空\n");
   }
   i = (Q->front) % MAXSIZE;
   do{
      printf("%d",Q->data[(i + 1 % MAXSIZE)]);
	  i = (i + 1) % MAXSIZE;
   }while(i != Q->rear);
}

/*算出对长*/
int getLength(CirclesQueue *Q){
  return(Q->rear - Q->front +MAXSIZE) % MAXSIZE;
}
/*找出对头*/
DataType getFront(CirclesQueue *Q){
  int i;
  i=(Q->front)%MAXSIZE;
  return  Q->data[(i +1%MAXSIZE)];
}

/*main.c*/
#include <stdio.h>
#include "CirclesQueue.h"


int main(int argc, char* argv[])
{
	CirclesQueue Q;
	DataType x;
	int cmd;
	char yn;


	do
	{	
		printf("-----------循环队列演示-----------\n");
		printf(" 1. 初始化\n");
		printf(" 2. 入队\n");
		printf(" 3. 出队\n");
		printf(" 4. 队空?\n");
		printf(" 5. 队满\n");
		printf(" 6. 输出队列\n");
		printf(" 7. 算出队长\n");
        printf(" 8. 找出队头\n");
		printf(" 0. 退出\n");
		printf(" 请选择(0~6):");
		scanf("%d",&cmd);
		switch(cmd)
		{
		case 1:
			init(&Q);
			printf("队列已初始化!\n");
			break;
		case 2:
			printf("请输入要入队的元素x=");
			scanf("%d", &x);
			if(!enqueue(&Q,x))
			{
				printf("元素x=%d已入队\n", x);
			}
			break;
		case 3:
			printf("确定要出队(出队会将删除对首元素, y or n, n)?");
			flushall();
			scanf("%c", &yn);

			if(yn == 'y' || yn == 'Y')
			{
				if(!dequeue(&Q,&x))
				{
					printf("队首元素【%d】已出队!\n", x);
				}
			}
			break;

		case 4:
			if(isempty(&Q)){
			printf("队列为空\n");
			}
			else{
			 printf("队列不为空\n");
			}
           break;

		   case 5:
			if(isfull(&Q)){
			 printf("队列已满\n");
			}
			else{
			  printf("队列未满\n");
			}
			break;

		   case 6:
			   printf("输出队列\n");
			   printQueue(&Q);
			   break;

		   case 7:
           printf("输出对长:%d \n",getLength(&Q));
           break;
    
		   case 8:
			   printf("找出对头:%d \n",getFront(&Q));
		}	
	}while(cmd!=0);
	return 0;
}


/*
	CirclesQueue.h
	循环队列
*/

#define MAXSIZE 100

typedef int DataType;

typedef struct
{
	DataType data[MAXSIZE];
	int front;
	int rear;
}CirclesQueue;

/*循环队列初始化*/
int init(CirclesQueue *Q);

/*入队*/
int enqueue(CirclesQueue *Q, DataType x);

/*队满?*/
int isfull(CirclesQueue *Q);

/*出队*/
int dequeue(CirclesQueue *Q, DataType *);

/*队空*/
int isempty(Ci


五.小结

1.循环队列是一种先进先出(FIFO)的数据结构,它可以在固定大小的数组中实现队列的操作。比较与之前的顺序表而言,循环队列的效率 结构上面的有这很大的便利:

 a.头指针(rear)和尾指针(front)可以同时操作,使得插入和删除操作更加高效。

 b.遵循先进先出原则在中间需要进行更多的遍历,在基础操作上更为方便

2.循环队列比较与顺序表有这很多方便而且具有高效的性能和使空间做到最大发挥

六.参考文献

1.csdn

2.老师代码

3.百度百科

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值