队列是一种先进先出的数据结构,可以作为一种缓存机制,在项目中常被用到。队列的实现可以基于链表和数组。链表的优点在于:取头尾元素以及向链表中插入元素的时间复杂度为O(1),且充分利用已分配的存储空间,绝不浪费。而数组由于是连续存储,所以存取元素的速度快。因此在STL中vector的应用要远多于list,以达到以最小的代价实现数据的连续存储。
STL queue是常用的队列,可以满足实际中的各种应用。STL queue实际上是一种适配器(adapter),其实现是基于STL的容器deque。deque是一种双端队列,是由一段段定量连续的空间组成,为了这种实现,deque使用了相对复杂的迭代器架构设计;因此在存取速度上不及数组。本文基于存取速度,用数组和模板实现循环队列,并和STL queue进行对比。
队列的实现代码如下:
#ifndef _SIMPLEQUEUE_H_
#define _SIMPLEQUEUE_H_
template <class Type>
class SimpleQueue
{
public:
//构造函数
SimpleQueue( );
//析构函数
~SimpleQueue();
//入队
bool EnQueue(const Type &);
//出队
bool DeQueue(Type &);
//判断队列是否满
bool IsFull()const;
//判断队列是否为空
bool IsEmpty()const;
private:
enum { nQueueSize = 1024 } ;
int nCurSize ; // 队列当前容量
int nCurFront ; // 当前队首的位置
int nCurRear ; // 当前队尾的位置
Type m_vQueue[nQueueSize];
};
template <class Type>
SimpleQueue<Type>::SimpleQueue( )
{
nCurSize = 0 ;
nCurFront = 0 ;
nCurRear = 0 ;
}
template <class Type>
SimpleQueue<Type>::~SimpleQueue( )
{
}
template <class Type>
bool SimpleQueue<Type>::EnQueue(const Type &element)
{
if( IsFull() )
{
return false;
}
m_vQueue[nCurRear++ % nQueueSize] = element ;
++nCurSize ;
return true;
}
template <class Type>
bool SimpleQueue<Type>::DeQueue(Type &element)
{
if( IsEmpty() )
{
return false;
}
element = m_vQueue[nCurFront++ % nQueueSize];
--nCurSize ;
return true;
}
template <class Type>
bool SimpleQueue<Type>::IsFull( )const
{
return nCurSize >= nQueueSize ;
}
template <class Type>
bool SimpleQueue<Type>::IsEmpty( )const
{
return nCurSize <= 0 ;
}
#endif
下面对SimpleQueue和STL queue的存取速度进行对比,向队列中插入1024个元素,然后进行出队,统计10000次实验所需的总时间。实验在32位CentOS release 5.5 (Final)CPU主频2094.750HZ的虚拟机上进行,时间结果为微秒。
#include "SimpleQueue.h"
#include <iostream>
#include <queue>
#include <cstdlib>
#include <sys/time.h>
using namespace std;
const int times = 10000 ;
const int nQueueSize = 1024 ;
int main()
{
//simplequeue
SimpleQueue<int> qi;
struct timeval tBegin;
struct timeval tEnd ;
int num ;
long long elapse ;
gettimeofday(&tBegin ,NULL);
srand(time(NULL));
for(int t = 0 ; t < times ;++t)
{
for(int i = 0 ; i < nQueueSize; ++i )
{
qi.EnQueue( (rand() % nQueueSize) );
}
while(!qi.IsEmpty())
{
qi.DeQueue(num);
}
}
gettimeofday(&tEnd ,NULL);
elapse = (tEnd.tv_sec - tBegin.tv_sec)*1000000 + (tEnd.tv_usec - tBegin.tv_usec);
cout<<"simpleQueue:"<<elapse<<"us"<<endl;
//stl queue
queue<int> stdqi;
gettimeofday(&tBegin ,NULL);
for(int t = 0 ; t < times ;++t)
{
for(int i = 0 ; i < nQueueSize; ++i )
{
stdqi.push( (rand() % nQueueSize) );
}
while(!stdqi.empty())
{
stdqi.pop();
}
}
gettimeofday(&tEnd ,NULL);
elapse = (tEnd.tv_sec - tBegin.tv_sec)*1000000 + (tEnd.tv_usec - tBegin.tv_usec);
cout<<"STLQueue:"<<elapse<<"us"<<endl;
return 0;
}
编译:g++ -g main.cpp -o run
运行结果为:
[root@localhost queue]# ./run
simpleQueue:686664us
STLQueue:958892us
可见在存取元素的速度上,simplequeue还是优于stlqueue,因此在数据量巨大,而又需要频繁存取队列时,如果对程序的运行时间有要求,那么STLqueue就存在可被替换的理由。当然,上述的比较并不能全面说明问题,STLqueue具有丰富的接口,鲁棒的实现,还是很多应用中的首选。