Read comments, type code, learn data structure-circular queue

Xiaomengxin talked to everyone today about what is a circular queue. Without further ado, let ’s get started!

If the circular queue can be used to solve the false full state of the queue, what is the false full state?

Assuming that the maximum space allocated in the current sequential queue is 6, when the tail pointer of the queue changes from the 5 subscript to the 6 subscript (the 6 subscript does not actually exist), it means that the queue is full at this time, but the dequeuing operation can still be performed. The queue cannot store and reallocate the array space like a sequential stack, so the actual available space of the queue is not full.

The circular queue is to construct the sequential queue into a circular queue space, as shown in the figure:
Insert picture description here

note:

At this time, when the pointer front = pointer rear, it is impossible to judge whether the queue space is full or empty, and there are two solutions:
1. Set another flag to distinguish whether the queue space is full or empty;
2. Use one less space and agree to " The queue head pointer is next to the queue tail pointer "as the queue full status flag.

come on! Let's take a chestnut, as shown in the figure:
[Case 1]
Insert picture description here
Initialization, the front of the team head pointer and the rear of the tail pointer all point to the 0 subscript;
when the data element 1 is stored, the rear pointer of the team tail from the 0 subscript to 1 subscript
When the data element 2 is stored, the tail pointer rear is from 1 subscript to 2 subscript;
when the data element 3 is stored, the tail pointer rear is from 2 subscript to 3 subscript;
when the data element 4 is stored, The tail pointer rear from the 3 index points to the 4 index;

When the data element 8 is stored, the tail pointer rear from the 7 index points to the 0 index; (the queue is full)
how to judge the front and rear pointers When rear coincides, is the queue empty or full? If we use flag to mark the coincidence state of the team head pointer front and the team tail pointer rear, then stipulate that when flag = 0: the queue is empty; when flag = 1, the queue is full.

[Case 2]
Insert picture description here
We leave the space of 7 subscripts without storing data. When the data element 7 enters the space of 6 subscripts, the tail pointer rear points to the space of 7 subscripts (the 7 subscript space is empty at this time) ), Theoretically, 8 spaces only use 7 spaces, but logically we stipulate that the queue is full at this time. When rear + 1, the front of the team head pointer coincides with the rear of the team tail pointer, indicating that the queue space logic is full at this time, we first put the elements of the space pointed by the team head pointer out of the team, and the team head pointer moves forward to the 1 subscript. At this time, the element is entered into the space with a subscript of 7, and the rear of the team pointer is moved forward (pointing to 0 subscript). When rear + 1, the front of the team head pointer and the rear of the team tail pointer coincide again, indicating the logic of the queue space at this time. It is full again, and iterate back and forth in turn, leaving the team—> the head of the team head moves forward—> then joins the team—> the tail of the team moves the rear pointer forward (after the judgment condition is rear + 1, the front of the team head and the tail of the team pointer) Whether rear coincides or not, you can continue to join the team).

However, the computer does not have a circular storage space, and it is still stored in a linear manner. How does the computer determine when the tail pointer and the head pointer overlap again?

————— OK! That is: modulo operation ——————

How the specific modular arithmetic is implemented, the text looks pale and weak, still that sentence, run the code and slowly realize!

#include <stdio.h>
#include <malloc.h>
#include <assert.h>

#define MAXSIZE 8//定义队列初始化存放8个数据元素
typedef int ElmeType;

/*给出顺序队列的结构*/
typedef struct Queue
{
	ElmeType *base;//指针base指向有效的队列空间
	int      front;//队头指针
	int      rear;//队尾指针指向下一个有效的空间
}Queue;

/*初始化顺序队列*/
void InitQueue(Queue *Q)
{
	Q->base=(ElmeType *)malloc(sizeof(ElmeType)*MAXSIZE);//开辟队列空间
	assert(Q->base!=NULL);//断言——是否开辟空间成功
	Q->front=Q->rear=0;//队头指针和队尾指针都指向队列的0下标,此时队列为空
}

/*入队*/
void EnQueue(Queue *Q,ElmeType x)
{
//数据入队后,队尾指针从当前空间指向下一个有效的空间,此时称队尾指针是伪指针;
//当伪指针所指下标+1后正好等于队列空间容量时,此时我们希望伪指针可以重新指向队头,而不是出界,于是进行模运算;

//(Q->rear+1)%MAXSIZE——若模为0,则伪指针恰好指向队列的最后一个有效空间,我们需要让此时的伪指针重新指向0下标而不是最后一个有效空间;
//(始终都要将队列最后一个有效空间空出)循环开始:
	if((Q->rear+1)%MAXSIZE==Q->front)//若伪指针所指下标+1与队头指针指向相同的下标,此时判断为队列逻辑已满
	return;//返回,理论上队列保留了队列最后一个有效空间
	Q->base[Q->rear]=x;//否则队列逻辑不满,继续在队尾指针所指下标进行入队,入队完成后,队尾指针又从当前空间指向下一个有效的空间
	Q->rear=(Q->rear+1)%MAXSIZE;//当逻辑空间满后,模运算实现队尾指针重新指向0下标而不是最后一个有效空间;
}

/*展示顺序队列元素*/
void ShowQueue(Queue *Q)
{
	printf("顺序队列中存放的元素:");
	for(int i=Q->front;i!=Q->rear;)
	{
		printf("%d ",Q->base[i]);//依次打印队头指针所指下标中的数据到队尾指针所指下标中的数据
		i=(i+1)%MAXSIZE;//循环打印,7下标不能打印,重新回到0下标(循环时,队尾下标-队头下标=-1)
	}
	printf("\n");
}

/*出队*/
void DeQueue(Queue *Q)
{
//出队一个元素,队头指针指向下一个有效的数据元素
	if(Q->front==Q->rear)//队头队尾指向相同,队列为空
		return;
	Q->front=(Q->front+1)%MAXSIZE;//队头指针循环,模运算实现队头指针重新指向0下标而不是最后一个有效空间;
}

/*取队头元素*/
void GetHead(Queue *Q,ElmeType *v)//指针v带回队头元素
{
//要获取队头,前提是队列不空
	if(Q->front==Q->rear)//队列为空
	return;
	*v=Q->base[Q->front];//必须在base所指的空间里取元素
}

/*顺序队列的长度*/
int Length(Queue *Q)
{
	return (Q->rear - Q->front);
	//下标0开始存放数据,进队后,队尾指针指向下一个有效的新空间
	//队列中元素的个数正好是队尾队头所指的下标之差
	//但是当队列逻辑空间满后,再存储数据需要先出队,再进行入队,此时队尾队头所指的下标之差为-1
}

/*清除顺序队列*/
void ClearQueue(Queue *Q)
{
	Q->front=Q->rear=0;//队列置为空
}

/*销毁顺序队列*/
void DestroyQueue(Queue *Q)
{
	free(Q->base);//释放base所指的队列空间
	Q->base=NULL;//预防野指针
}
/**/

void main()
{
	Queue Q;
	ElmeType e;//定义队头元素
	InitQueue(&Q);//&Q是传入队列的地址
	printf("将1,2,3,4,5,6,7,8依次入队\n");
	for(int i=1;i<=8;++i)
	{
		EnQueue(&Q,i);
	}
	ShowQueue(&Q);
	printf("顺序队的长度为:%d\n",Length(&Q));
	printf("\n");
	printf("进行出队\n");
	DeQueue(&Q);
	ShowQueue(&Q);
	GetHead(&Q,&e);
	printf("队头元素为:%d\n",e);
	printf("\n");
	printf("将元素10入队\n");
	EnQueue(&Q,10);
	ShowQueue(&Q);
	printf("\n");
	printf("进行出队\n");
	DeQueue(&Q);
	ShowQueue(&Q);
	GetHead(&Q,&e);
	printf("队头元素为:%d\n",e);
	printf("\n");
	printf("将元素20入队\n");
	EnQueue(&Q,20);
	ShowQueue(&Q);
	printf("\n");
	ClearQueue(&Q);
	DestroyQueue(&Q);
}

operation result:
Insert picture description here

Published 23 original articles · praised 46 · visits 2056

Guess you like

Origin blog.csdn.net/weixin_43964458/article/details/105399987