循环队列
为什么需要循环队列?
我的理解:系统的内存一般是有边界的。像栈、链表这种数据结构的位置一般是稳定的,无非是变长变短;但是队列就不一样了,在执行入队出队的操作时,数据内存整体会呈现出一种不断向后撤的姿态,一旦它撤到内存的边界,就会出现一系列错误。
循环队列的结构设计
由于循环对列给定了数据范围的大小,则不需要使用链式的动态创建方法了(如果依旧使用链式存储,会无法确定何时再回到队头进行插入操作),因此我们采用模拟的方法。
data表示一个数据域,int为类型,其可以修改为任意自定义的类型,比如说简单的char,float类型等等,也可以是复杂的结构体类型,我们使用maxsize表示循环队列的最大容纳量,其表示队列的全部可操作空间。
rear代表尾指针,入队时移动。
front代表头指针,出队时移动。
- rear和front说是指针,其实是一个整数,因为data是在数组中储存的,所以整数也能实现类似指针的效果。
- 因为用的是数组,所以循环队列的大小在一开始就是规定好的。
#define maxsize 10 //表示循环队列的最大容量
//循环队列的结构设计
typedef struct cir_queue{
int data[maxsize];
int rear;
int front;
}cir_queue;
初始化
//初始化
cir_queue *init(){
cir_queue *q = (cir_queue*)malloc(sizeof(cir_queue));
if(q==NULL){
exit(0); //申请内存失败,退出程序
}
q->front=0;
q->rear=0;
return q;
}
//让rear和front都指向第一个结点(也就是数组[0]的位置)。
操作---入队
入队操作同顺序队列的方法,直接将rear向后移动即可,但是要注意判断,如果rear达到了队列的空间上线,将要从头继续开始移动,这里推荐使用余数法,即无论如何求余都是在这片空间内进行操作,防止一次错误执行就直接整体崩溃,而且也相对而言更为简洁,不推荐使用if语句,这样显得比较累赘。
//入队操作push
void push(cir_queue *q,int data){
if((q->rear+1)%maxsize==q->front){
printf("溢出,无法入队\n");
return;
}else{
q->rear=(q->rear+1)%maxsize;
q->data[q->rear]=data;
}
}
//先判断队是否是满的,再去移动。
操作---出队
//出队操作pop
void pop(cir_queue *q){
if(q->rear==q->front){
printf("队列为空,无法出队\n");
return;
}else{
q->data[q->front]=0;
q->front=(q->front+1)%maxsize;
}
}
操作---遍历
//遍历队列
void print(cir_queue *q){
int i=q->front;
while(i!=q->rear){
i=(i+1)%maxsize;
printf("%d\t",q->data[i]);
}
printf("\n"); //记得换行
}
完整代码
#include<stdio.h>
#include<stdlib.h>
#include<cstring>
#define maxsize 10 //表示循环队列的最大容量
//循环队列的结构设计
typedef struct cir_queue{
int data[maxsize];
int rear;
int front;
}cir_queue;
//初始化
cir_queue *init(){
cir_queue *q = (cir_queue*)malloc(sizeof(cir_queue));
if(q==NULL){
exit(0); //申请内存失败,退出程序
}
memset(q->data,0,sizeof(q->data));
q->front=0;
q->rear=0;
return q;
}
//入队操作push
void push(cir_queue *q,int data){
if((q->rear+1)%maxsize==q->front){
printf("溢出,无法入队\n");
return;
}else{
q->rear=(q->rear+1)%maxsize;
q->data[q->rear]=data;
}
}
//出队操作pop
void pop(cir_queue *q){
if(q->rear==q->front){
printf("队列为空,无法出队\n");
return;
}else{
q->data[q->front]=0;
q->front=(q->front+1)%maxsize;
}
}
//遍历队列
void print(cir_queue *q){
int i=q->front;
while(i!=q->rear){
i=(i+1)%maxsize;
printf("%d\t",q->data[i]);
}
printf("\n"); //记得换行
}
int main(){
cir_queue *q = init();
////////////入队操作///////////////
printf("入队操作\n");
for(int i=1;i<=6;i++){
push(q,i);
}
print(q);
////////////出队操作///////////////
printf("出队操作\n");
for(int i=1;i<=3;i++){
pop(q);
print(q);
}
return 0;
}