循环队列的基本操作
刚把数据结构里面的队列学习了一下,主要是对循环队列的基本操作进行了了解,主要是想明白,循环队列的循环是咋实现的,就好了,然后把入队和出队,判断是否是空,和判断是否为满的弄懂就搞清楚循环队列了。
队列
如图所示,队列是一种可以实现“先进先出”的存储结构,哪一个节点元素先进来,它最先出去,然后如果想继续加入节点,就在队伍的最后面加入。
队列分为链式队列(用链表实现的)和静态队列(也就是循环队列),在这篇博客里主要讲的是循环队列的基本操作。
循环队列
循环队列是靠数组来实现的,就是如图所示一样的哈,想一条蛇,收尾相连,具体如何收尾相连,就是靠很简单的取余来实现的哈,对数组的长度进行取余,就可以循环了哈。//如果这里不懂,看下面,继续讲解的哈。
参数font/rear
在好多书上讲的是font是指向队头,rear是指向队尾,但是这个操作起来不方便。下面分情况讨论
1.队列初始化
font和rear都为0//不懂的看上图
2.队列非空的时候(就是放值的时候)
font是队列第一个元素
rear为队列最后一个有效元素的下一个元素//这样好操作
3.队列为空
这个判断起来很简单
当font和rear相等的时候,但不一定为0
定义的结构体
typedef struct Queue{
int *pBase;
//这个是用来当定义的数组的首地址的
int front;
//队头数组的下标
int rear;
//队列最后一个有效元素的下一个元素的下标
}QUEUE,*PQUEUE;
初始化
先创建好数组空间
然后初始化font和rear都为0
下面这个是创了一个6个int类型元素的数组,首地址为pQ->pBase
void init(PQUEUE pQ){
pQ->pBase = (int *)malloc(sizeof(int)*6);
pQ->front = 0;
pQ->rear = 0;
}
判断循环队列是否为满
判断循环队列是否为满有2种使用的方法
1.加个参数,记录有效节点数,入队就+1,出对就-1,判断是否为满,就看它是否和创建的数组最大元素个数是否相同,但是不建议用这个方法,因为你还要重新开辟空间
2.浪费一个空间,数组只能放(n-1)个元素,一开始font和rear相同,不断入队,rear就在圈上往上走,当它快走一圈的时候,也就是rear紧挨这个font
就是当(rear+1)%数组的长度==front的时候
满了
bool full_queue(PQUEUE pQ){
if((pQ->rear +1)%6 == pQ->front){
return true;
}else{
return false;
}
}
判断是否为空
这个最简单,就是他们font和rear相等的时候
bool out_queue(QUEUE*pQ,int *pVal){
if(empty_queue(pQ)){
return false;
}else{
*pVal = pQ->pBase[pQ->front];
pQ->front = pQ->front+1;
}
}
入队
先判断下队列是否为满
如果不满的话,入队
很简单,把元素放在rear的位置就好了(之前定义说过,rear为队列最后一个有效元素的下一个元素)
然后 rear=rear+1//这个不准确
又因为是循环队列哈
真正的 rear = (rear+1)%数组的长度
bool en_queue(PQUEUE pQ,int val){
if(full_queue(pQ)){
return false;
}else{
pQ->pBase[pQ->rear] = val;
pQ->rear = (pQ->rear+1) % 6;
returnt
ue;
}
}
出队
先判断队列是否为空
如果是空的话就不出队了
出队的话也很简单
就是把font=font+1//这个不准确
因为是循环的哈,所以font = (font+1)%数组长度,,在这个函数里,我还把出队的元素记录了下来
bool out_queue(QUEUE*pQ,int *pVal){
if(empty_queue(pQ)){
return false;
}else{
*pVal = pQ->pBase[pQ->front];
pQ->front = pQ->front+`
;
}
}
总的代码
这个循环队列只是我定义为int类型的数组,里面有6个元素,这个可以自己修改,在初始化那块改的
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
/*队列的基本运用
所有和时间的操作都和队列有关
*/
typedef struct Queue{
int *pBase;
int front;
int rear;
}QUEUE,*PQUEUE;
void init(PQUEUE);
bool en_queue(PQUEUE,int);
void traverse_queue(PQUEUE);
bool full_queue(PQUEUE);
bool out_queue(PQUEUE,int *);
bool empty_queue(PQUEUE);
bool empty_queue(PQUEUE pQ){
if(pQ->front ==pQ->rear){
return true;
}else{
return false;
}
}
bool out_queue(QUEUE*pQ,int *pVal){
if(empty_queue(pQ)){
return false;
}else{
*pVal = pQ->pBase[pQ->front];
pQ->front = pQ->front+1;
}
}
bool full_queue(PQUEUE pQ){
if((pQ->rear +1)%6 == pQ->front){
return true;
}else{
return false;
}
}
void init(PQUEUE pQ){
pQ->pBase = (int *)malloc(sizeof(int)*6);
pQ->front = 0;
pQ->rear = 0;
}
bool en_queue(PQUEUE pQ,int val){
if(full_queue(pQ)){
return false;
}else{
pQ->pBase[pQ->rear] = val;
pQ->rear = (pQ->rear+1) % 6;
return true;
}
}
void traverse_queue(PQUEUE pQ){
int i = pQ->front;
while(i!=pQ->rear){
printf("%d ",pQ->pBase[i]);
i = (i+1)%6;
}
}
int main(void){
QUEUE Q;
int val;
init(&Q);
en_queue(&Q,1);
en_queue(&Q,2);
en_queue(&Q,3);
en_queue(&Q,4);
en_queue(&Q,5);
en_queue(&Q,6);
en_queue(&Q,7);
en_queue(&Q,8);
traverse_queue(&Q);
if(out_queue(&Q,&val)){
printf("出队 %d\n",val);
}else{
printf("失败\n");
}
traverse_queue(&Q);
return 0;
}
总结
这个循环队列,只要理解循环是咋弄的就很简单了哈