像栈一样,队列(queue)也是表。然而,使用队列时插入在一端进行而删除则在另一端进行,也就是先进先出(FIFO)。队列的基本操作是EnQueue(入队),它是在表的末端(叫做队尾(rear))插入一个元素;还有DeQueue(出队),它是删除(或返回)在表的开头(叫做队头(front))的元素。
同样,队列也可以由链表或数组实现,特点分析如下:
链表:不需要设定空间大小,也不会浪费空间;插入或删除时需要动态分配或删除内存,比较耗时;不支持随机存取;
数组:需要预知需要空间的大小,会造成空间浪费或不够用;插入或删除不需要动态分配或删除内存,耗时很小;支持随机存取。
另外,队列又有链式队列和循环队列两种。本文给出用单链表实现的链式队列(循环队列可类似地用循环列表实现)和用数组实现的循环队列(当数组空间够大时,链式队列和循环队列是一样的)。
下面是用单链表实现的队列:
/*queue.h (slist.h is the header file /*queue.h (slist.h is the header file for class SList)*/
#include "slist.h"
template<typename T>
class Queue
{
public://不需要自行定义copying函数,编译器自动的合成的版本工作正常:调用基类和各个数据成员的相应的copying函数。
Queue();
Queue(const T& initdata);
~Queue();
public:
int IsEmpty() const;
int GetCount() const;
void MakeEmpty();
int EnQueue(const T data);
T DeQueue();
T& GetFront();
T GetFront() const;
T& GetRear();
T GetRear() const;
private:
SList<T> slist;
};
template<typename T>
inline Queue<T>::Queue():slist()
{}
template<typename T>
inline Queue<T>::Queue(const T& initdata):slist(initdata)
{}
template<typename T>
inline Queue<T>::~Queue()
{}
template<typename T>
inline int Queue<T>::IsEmpty() const
{
return slist.IsEmpty();
}
template<typename T>
inline int Queue<T>::GetCount() const
{
return slist.GetCount();
}
template<typename T>
inline void Queue<T>::MakeEmpty()
{
slist.RemoveAll();
}
template<typename T>
inline int Queue<T>::EnQueue(const T data)
{
return slist.AddTail(data);
}
template<typename T>
inline T Queue<T>::DeQueue()
{
T data = slist.GetHead();
slist.RemoveHead();
return data;
}
template<typename T>
inline T& Queue<T>::GetFront()
{
return slist.GetHead();
}
template<typename T>
inline T Queue<T>::GetFront() const
{
return slist.GetHead();
}
template<typename T>
inline T& Queue<T>::GetRear()
{
return slist.GetTail();
}
template<typename T>
inline T Queue<T>::GetRear() const
{
return slist.GetTail();
}
#endif // __LIST_QUEUE_H__
下面是利用数组实现的循环队列:
/*queuearray.h*/
#ifndef __LIST_QUEUEARRAY_H__
#define __LIST_QUEUEARRAY_H__
#include <assert.h>
const int MinQueueSize=5;
const int MaxQueueSize=500;
template<typename T>
class QueueArray
{
public:
QueueArray(int maxsize=MaxQueueSize);
QueueArray(const QueueArray<T>& other);
QueueArray<T>& operator=(const QueueArray<T>& other);
~QueueArray();
public:
int IsEmpty() const;
int IsFull() const;
int GetCount() const;
void MakeEmpty();
int EnQueue(const T& data);//size++, rear++(use circlar array) and array[rear]=data.
T DeQueue();//return array[front], size-- and front++(use circlar array)
T& GetFront();
T GetFront() const;
T& GetRear();
T GetRear() const;
private:
int Succession(int pos);//to implement circluar queue using circular array.
private:
int capacity;
int front;
int rear;
int size;
T *array;
};
template<typename T>
inline QueueArray<T>::QueueArray(int maxsize):capacity(maxsize),front(1),rear(0),size(0),array(NULL)
{
ASSERT(capacity>=MinQueueSize);
try
{
array=new T[capacity];
}
catch(std::bad_alloc&)
{
}
}
template<typename T>
inline QueueArray<T>::QueueArray(const QueueArray<T>& other):capacity(other.capacity),front(other.front),rear(other.rear),size(other.size),array(NULL)
{
if(capacity>0)
{
try
{
array=new T[capacity];
}
catch(std::bad_alloc&)
{
}
for(int i=0;i<capacity;i++)
{
array[i]=other.array[i];
}
}
}
template<typename T>
inline QueueArray<T>& QueueArray<T>::operator=(const QueueArray<T>& other)
{
if(this==&other)
{
return *this;
}
if(array!=NULL)
{
delete [] array;
}
capacity=other.capacity;
size=other.size;
front=other.front;
rear=other.rear;
if(capacity>0)
{
try
{
array=new T[capacity];
}
catch(std::bad_alloc&)
{
}
for(int i=0;i<capacity;i++)
{
array[i]=other.array[i];
}
}
return *this;
}
template<typename T>
inline QueueArray<T>::~QueueArray()
{
if(array)
{
delete [] array;
}
}
template<typename T>
inline int QueueArray<T>::IsEmpty() const
{
return 0==size;
}
template<typename T>
inline int QueueArray<T>::IsFull() const
{
return capacity==size;
}
template<typename T>
inline int QueueArray<T>::GetCount() const
{
return size;
}
template<typename T>
inline void QueueArray<T>::MakeEmpty()
{
front=1;
rear=0;
size=0;
}
template<typename T>
inline int QueueArray<T>::Succession(int pos)
{
if(++pos==capacity)
{
pos=0;
}
return pos;
}
//size++, rear++(use circlar array) and array[rear]=data.
template<typename T>
inline int QueueArray<T>::EnQueue(const T& data)
{
if(IsFull())
{
return 0;
}
else
{
size++;
rear=Succession(rear);
array[rear]=data;
return 1;
}
}
//return array[front], size-- and front++(use circlar array)
template<typename T>
inline T QueueArray<T>::DeQueue()
{
ASSERT(0 != size);
T data=array[front];
size--;
front=Succession(front);
return data;
}
template<typename T>
inline T& QueueArray<T>::GetFront()
{
ASSERT(0 != size);
return array[front];
}
template<typename T>
inline T QueueArray<T>::GetFront() const
{
ASSERT(0 != size);
return array[front];
}
template<typename T>
inline T& QueueArray<T>::GetRear()
{
ASSERT(0 != size);
return array[rear];
}
template<typename T>
inline T QueueArray<T>::GetRear() const
{
ASSERT(0 != size);
return array[rear];
}
#endif //for __LIST_QUEUEARRAY_H_