思考:
我们在上一个队列可以进行插入和删除操作 , 但是我们不能直接得出元素个数 , 我们会联想到队首指针和队尾指针 ,元素个数之间的关系 , 知其二 即可知其一 ,并且我们有了 count(计算元素个数的标志) , 就可以知道什么时候队满了 ,然后当 front 和 rear 重合时 , 我们通过队列中元素个数 , 也能区分出队满和 队空了 , 那我们的最大存储容量就是 MaxSize 了
● 问题
• 如果知道环形队列队头指针 front 和队列中元素个数 count , 则可以计算出队尾指针 .
• 存储环形队列时 , 可以记录队列中队头指针front 和队列中元素个数count , 而不记录队尾指针 rear;
front , rear , count 三者择其一
●已知 front , rear , 求队中元素个数 :
count = (rear - front+MaxSize)%MaxSize
队尾指针 - 队首指针 算出两者距离 , 即为元素个数 , 逻辑上是正确的,但是我们是循环队列 ,所以当 rear 转了一圈,过了 0 位序 ,但是 front 没过零位序 ,会导致两者为负,原因是 rear 变成 0 ,相当于减去了 MaxSize ,所以加上MaxSize 就可以了
然后,我们又取余的含义是 , 当两者循环了很多次后 , count数值会变超过数组位序, 我们要让其变成实际上的个数
● 已知 front , count ,求 rear ;
rear = (front + count)%MaxSize
如上图所以 , 队首指针加上元素个数 ,即为rear指向的位序
●已知 rear ,count ,求 front
front = (rear - count + MaxSize)%MaxSize
同理 ,队尾指针减去 元素个数 加上 MaxSize ,防止负数 ,然后取余即可
下面开始 只记录 队头front 和元素个数 count 的方案
定义结构体
typedef struct { ElemType data[MaxSize]; int front; int count; }QuType;
我们的队尾指针可以通过运算得到 , 所以不必定义
● 环形队列的四要素
• 队空条件: count = 0;
count 计算元素个数
• 队满条件 : count = MaxSize
有了 count, 我们就不依赖于 front 和 rear 来标志队空和队满了 , 那队存储的最大容量也是数组的容量了, count = MaxSize
• 进队操作 :rear = (rear+1)%MaxSize ;将入队元素 e 放在 rear处(rear 由 front 和 count定)
当队不满时候 ,就可以入队 ,rear 向后移动一位 , 我们的rear虽然没定义 ,但可以由front 和 count 计算得出
•出队操作 : front =(front + 1)%MaxSize ; 取出front处元素e ;
当队列不空时候 , 就代表队列里面有元素 ,就可以出队
下面开始代码实现:
●初始化队列运算算法
//传入要创建的队列名称的指针地址 void InitQueue(QueType *&qu) { //为队列结构分配空间 qu = (QuType *)malloc(sizeof(QuType)); //队列的队首指针和队尾指针指向 0 qu -> front = 0; qu -> count = 0; }
● 判断队空的运算算法
//队空运算算法 //传入要判断队列的指针 bool QueueEmpty(QuType *qu) { //空则返回true return(qu->count == 0); }
● 判断队满的运算
//队空运算算法 //传入要判断队列的指针 bool QueueFull(QuType *qu) { //满队则返回 true return(qu -> count == MaxSize); }
● 出队运算算法
//传入要出队的队列 ,和保存存入元素的变量地址 bool DeQueue(QuType *&qu, ElemType &x) { //先判断是否是空队 ,空队则队下溢,返回错误 if(qu->count == 0) { //队空返回错误 return false; } else { //队不空则队首指针向后位移一位,然后传出元素,队列元素个数减一 qu->front = (qu->front+1)%MaxSize; //传出元素 x = qu->data[qu->front]; //队列个数减一 qu->count--; //出队成功返回true return true; } }
● 进队运算算法
//进队运算算法 //传入要进队的队列 , 和存储进队的元素 { //进队要用到rear ,我们之前没有定义,所以这里定义运算一下 int rear; //先判断是否队满 if(qu->count == MaxSize) { //满则返回错误 return false; } else { //不满则把尾指针算出 ,然后尾指针后移一位,插入新元素 ,队元素个数加一 rear = (qu->front+qu->count)%MaxSize; //尾指针后移一位 rear = (rear+1)%MaxSize; //插入新元素 qu->data[rear] = x; //队元素个数加一 qu->count++; return true; } }