循环队列
此前我在这篇博客中提出了假溢出的概念:
----->https://blog.csdn.net/qq_38193883/article/details/97661165
因为还有大量实际空间未被占用,此时又不应该扩充数组。但继续添加节点又会造成数组越界,所以我们请本篇大Boss出场
循环队列:简单描述就是有两个指针,一个是指向队头的front,另一个是指向队尾rear
-
问题1: 如果rear或者front转完一圈如何回来呢?(循环队列如何实现循环呢?) 解答: 我们使用C语言中mod:%运算来实现循环,即: front<==>(front)%MAXsize; rear<==>(rear)%MAXsize;
-
问题2: 从图中不难发现我画了一个灰色区域不可用,为什么要浪费一个空间呢?
解答: 试想如果不浪费该空间,队满队空的条件是什么?
队满:Q.front==Q.rear;
队空:Q.front==Q.rear;
所以如果Q.front==Q.rear我们无法区分此刻到底是处于队空还是队满状态
但 设置灰色不可用区域(浪费一个空间不使用)后:
队空:Q.front==Q.rear
队满:(Q.rear+1)=Q.front
OK,接下来我们一起来看循环链表的基本操作:
-
定义:
typedef struct{ Qelemtype *base; int front; int rear; }CirQueue,*Cir;
-
初始化(创建空循环链表)
Cir Init_CirQueue(Cir Q)
{
Q=(Cir)malloc(sizeof(CirQueue));
Q->base=(int*)malloc(sizeof(int)*MAXsize);//要为base开辟空间
Q->front=0;
Q->rear=0;
return Q;
}
-
入队操作:(入队时需注意的是判断队列是否已满)
核心步骤: 1: Q->base[Q.rear]=e;//将数据放入 2:Q->rear=(Q.rear+1)%MAXsize;//尾结点后移一位
int Insert_CirQueue(Cir Q,Qelemtype e){
int r=Q->rear;
if((r+1)%MAXsize==Q->front){//如果队满就不允许加入了
return -1;//记住留一个空位哦~,这样便于以后区分队空队满
}
Q->base[r]=e;//将数据放入
Q->rear=(r+1)%MAXsize;//尾结点后移一位
return 1;
}
-
出队操作:(出队时需要判断队列是否已经为空)
核心步骤: Q->front=(Q->front+1)%MAXsize;//front后移一位
int Del_CirQueue(Cir Q,Qelemtype &e){
if(Q->front==Q->rear){
return -1;
}
printf("结点%d出列\n",Q->base[Q->front]);
Q->front=(Q->front+1)%MAXsize;//front后移一位
return 1;
}
-
遍历:
void visit(Cir Q){
if(Len_CirQueue(Q)==0){
printf("队列已空!\n");
return ;
}
int q = Q->front;
while((q%MAXsize)!=Q->rear){
q++;//只要q没有遍历到尾结点就一直向下遍历
}
}
-
测试程序(AC)
/*循环队列设有两个指针,一个是指向队头的front,另一个是指向队尾rear
如果rear或者front转完一圈如何回来呢?(循环队列如何实现循环呢?)
浪费一个空间不用,理由:
试想如果不浪费该空间,队满队空的条件是什么?
队满:Q.front==Q.rear
队空:Q.front==Q.rear
所以如果Q.front==Q.rear我们无法判别到底是队空还是队满
设置灰色不可用区域后:
队空:Q.front==Q.rear
队满:(Q.rear+1)=Q.front
*/
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#define MAXsize 100
#define Qelemtype int
typedef struct{
Qelemtype *base;
int front;
int rear;
}CirQueue,*Cir;
Cir Init_CirQueue(Cir Q)
{
Q=(Cir)malloc(sizeof(CirQueue));
Q->base=(int*)malloc(sizeof(int)*MAXsize);//要为base开辟空间
Q->front=0;
Q->rear=0;
return Q;
}
int Len_CirQueue(Cir Q)
{
return (Q->rear - Q->front + MAXsize)%MAXsize;
}
int Insert_CirQueue(Cir Q,Qelemtype e){
int r=Q->rear;
if((r+1)%MAXsize==Q->front){//如果队满就不允许加入了
return -1;//记住留一个空位哦~,这样便于以后区分队空队满
}
Q->base[r]=e;//将数据放入
Q->rear=(r+1)%MAXsize;//尾结点后移一位
return 1;
}
int Del_CirQueue(Cir Q,Qelemtype &e){
if(Q->front==Q->rear){
return -1;
}
printf("结点%d出列\n",Q->base[Q->front]);
Q->front=(Q->front+1)%MAXsize;//front后移一位
return 1;
}
void visit(Cir Q){
if(Len_CirQueue(Q)==0){
printf("队列已空!\n");
return ;
}
printf("此时队列中的元素有:\n");
int q = Q->front;int i=1;
while((q%MAXsize)!=Q->rear){
printf("第%d个:%d \n",i,Q->base[q]);
q++;i++;
}
printf("---------------------------------\n");
}
int main(){
Cir Q;
int num;int e;int a[MAXsize];
Q=Init_CirQueue(Q);
printf("您想建立几个节点的循环链表?\n");
scanf("%d",&num);
for(int i=0;i<num;i++){
scanf("%d",&a[i]);
Insert_CirQueue(Q,a[i]);
}
printf("链表长为%d个\n",Len_CirQueue(Q));
visit(Q);
Del_CirQueue(Q,e);
visit(Q);
Insert_CirQueue(Q,a[0]);
printf("您输入的第一个数据再次入队后") ;
visit(Q);
}
-
正经致谢:
-
【代码跑的时候一直运行不出,结果发现初始化操作一直有问题, 调试了好久发现main里已经分配好了地址空间,初始化里又分配了一次,天哪........(自闭中)】