大道至简—循环队列
一、前言
队列可能是大家学习linux通讯时接触到的知识,当然也是我们在编程中使用较多的一个点,其中最主要的一方面用来降低程序之间的耦合度,还有异步操作;
前段时间在公司写了一个小的服务,同样使用了队列对服务进行了异步操作,知识队列没有使用现有的一些大型库,自己使用了原生的STL队列中的接口,进行了简单的封装,当前对代码调优不够,后来才发现有很多的漏洞影响着性能;其中就有一条是引发今天这篇文章的元素——在程序中,需要不断的申请释放内存,这样就影响了程序的性能;
使用循环队列就可以很轻松的解决上述问题,在程序开始的时候就申请内存,在程序结束的时候释放内存,这样就避免了程序不断的申请释放内存带来的消耗~
二、假溢出
“假溢出”是什么?其实用大白话来说就是明明还有空间可以存储数据,但是程序却告诉你你没有空间可以存储数据了!
案例:
比如一个队列que,头是front,尾是end,队列长度是L;当front等于-1时队空,rear等于L-1时为队满;队列一般是头部插入,尾部取出;当尾部等于L-1时,但是front不等于-1,这个队列并没有真正满载,所以就会造成假溢出,这个就是假溢出的来源~

解决:
其实类似这种情况的出现只有在规定链表长度的时候才会使用,一般我们编写队列的时候,在数据量不是特别大的时候,不会规定队列的大小,但是我们在特定情况下编写就需要考虑这种情况的发生~
-
使用循环队列;通过首位连接的方式,判断队列是否满
-
使用移动的方式,使队列平移
三、循环队列的实现

实现循环队列时需要注意判断循环队列是否满或者是否空,判断队列是否满有两种方法:
-
使用标志位判断循环队列是否为空
-
在循环队列下,仍定义front=rear时为队空,而判断队满则用两种办法,一是用“牺牲一个单元”,即rear+1=front(准确记是(rear+1)%m=front,m是队列容量)时为队满。
第二种方案其实需要判断多个条件,网上一些代码是有问题,希望火眼金睛~
这里使用的第一种使用标记的方式标记了队列空和满的方式:
代码实现以及测试:
cirque.h
#ifndef _CIRQUE_H_#define _CIRQUE_H_#include <iostream>#include <queue>using namespace std;class CIRQUE{public: CIRQUE(int size); ~CIRQUE(); //队列是否为空 bool IsEmpty(); //清空队列 void ClearQue(); //队列是否满 bool IsFull(); //入队操作 bool InsetQue(int val); //出队操作 bool PopQue(int &val); //获取当前循环队列中的元素 int getNumQue();private: int m_size; //队列头 int m_head; //队列尾 int m_tail; //数组指针 int* m_pQue; //队列数量 int m_QueNum; //标志位--是否为空 bool bEmpty; //标志位--是否满 bool bFull;};#endif
cirque.cpp
#include "cirque.h"CIRQUE::CIRQUE(int size){ m_size = size; m_pQue = new int[m_size]; ClearQue();}CIRQUE::~CIRQUE(){ delete[] m_pQue; m_pQue = NULL;}bool CIRQUE::IsEmpty(){ return bEmpty;}void CIRQUE::ClearQue(){ m_head = m_tail = 0; m_QueNum = 0; bEmpty = true; bFull = false;}bool CIRQUE::IsFull(){ return bFull;}bool CIRQUE::InsetQue(int val){ if (IsFull()) { cout << "queue is full" << endl; return false; } m_tail = (m_tail+1) % m_size; m_pQue[m_tail] = val; m_QueNum++; bEmpty = false; if (m_QueNum == m_size) { bFull = true; } return true;}bool CIRQUE::PopQue(int &val){ if (IsEmpty()) { cout << "队列为空,不能出队" << endl; return false; } m_QueNum--; if (m_QueNum == 0) { bEmpty = true; } m_head = (m_head+1) % m_size; val = m_pQue[m_head]; return true;}int CIRQUE::getNumQue(){ return m_QueNum;}
main.cpp
#include "cirque.h"int main(){ int val = 0; CIRQUE CIR(4); CIR.InsetQue(10); CIR.InsetQue(11); CIR.InsetQue(12); CIR.PopQue(val); CIR.InsetQue(17); CIR.InsetQue(17); CIR.InsetQue(17); CIR.InsetQue(17); cout << "val:"<<val << endl; cout << "num:"<< CIR.getNumQue() << endl; CIR.InsetQue(17); return 0;}
结果展示:

四、往期精彩汇总
欢迎关注公众号---后台服务器开发,更多精彩等你来看~