循环队列

                                            循环队列

此前我在这篇博客中提出了假溢出的概念:

                                       ----->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里已经分配好了地址空间,初始化里又分配了一次,天哪........(自闭中)】

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值