Xiaomengxinは今日、循環キューとは何かについて皆に話しました。さっそく始めましょう。
循環キューを使用してキューの誤った完全状態を解決できる場合、誤った完全状態とは何ですか?
現在のシーケンシャルキューに割り当てられている最大スペースが6であるとすると、キューのテールポインターが5の添え字から6の添え字に変化すると(6の添え字は実際には存在しません)、キューはこの時点でいっぱいですが、デキュー操作は引き続き実行できます。キューはシーケンシャルスタックのように配列スペースを格納および再割り当てできないため、キューの実際に使用可能なスペースがいっぱいではありません。
循環キューは、図に示すように、順次キューを循環キュースペースに構築します。
注:
このポインタは、フロントでの時間、= REARポインタでは、キューが満杯または空のスペースないと判断され、2つの解決策があります
また、キューが満杯または空のスペースであるフラグビットがあります1。
2.小さいスペースに合意しています」キューヘッドポインターは、キューフルステータスフラグとしてキューテールポインターの隣にあります。
さあ!図に示すように、栗を取ってみましょう:
[Case 1]
初期化、チームヘッドポインターの前部とテールポインターの後部はすべて0の添え字を指します。
データ要素1が格納されると、チームテールの後部ポインターは0の添え字から1の添え字になります。
データ要素2が格納されている場合、テールポインターの後部は1添え字から2添え字までです。
データ要素3が格納されている場合、テールポインター後部は2添え字から3添え字までです。
データ要素4が格納されている場合、 3インデックスから後ろのテールポインターは4インデックスを指します
…
データ要素8が格納されている場合、7インデックスから後ろのテールポインターは0インデックスを指します(キューがいっぱいです)
フロントポインターとリアポインターを判断する方法後方が一致する場合、キューは空ですか、それともいっぱいですか?フラグを使用してチームヘッドポインターフロントとチームテールポインターリアの一致状態をマークする場合、フラグ= 0の場合:キューは空であり、フラグ= 1の場合、キューはいっぱいであることを規定します。
【事例2】
データを格納せずに添え字7個分のスペースを残すデータ要素7が添え字6個分のスペースに入ると、テールポインタ後方が添え字7個分のスペースを指す(現時点では添え字7個分のスペースは空) )、理論的には、8つのスペースは7つのスペースのみを使用しますが、論理的には、現時点ではキューがいっぱいであることを規定しています。リア+ 1、チームヘッドポインターの前部がチームテールポインターの後部と一致している場合、この時点でキュースペースロジックがいっぱいであることを示します。最初に、チームヘッドポインターが指すスペースの要素をチームの外に置き、チームヘッドポインターが1の添え字に進みます。このとき、要素は添え字7でスペースに入力され、チームポインターの後部が前方に移動します(0の添え字を指します)。後部+ 1の場合、チームヘッドポインターの前部とチームテールポインターの後部が再び一致し、このときのキュースペースのロジックを示します。再び満杯になり、順番に前後に繰り返し、チームを離れます—>チームヘッドの頭が前方に移動します>>チームに参加します>>チームの尾が後方ポインターを前方に移動します(判定条件が後方+ 1の後で、チームヘッドの前方とチームポインターの尾)リアが一致してもしなくても、チームに参加し続けることができます)。
ただし、コンピューターには循環ストレージスペースがなく、直線的に保存されます。コンピューターは、テールポインターとヘッドポインターが再びオーバーラップするタイミングをどのように決定しますか?
————— OK!つまり、モジュロ演算——————
特定のモジュラー演算がどのように実装されるかによって、テキストは青白くて弱く見えますが、それでもその文はコードを実行し、ゆっくりと実現します!
#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);
}
演算結果: