队列是一种十分常见的数据结构,具有先进先出的特点.队列在处理消息时,非常常用.本文利用C++,模板,链表来实现一个简单的队列.
代码解读如下:
1. QueueLinkList头文件. QueueLinkList私有继承于LinkList,因为做为队列中的核心链表数据结构,我们只希望其具有尾插入,头取出的方法. 采用private继承可以很好的保证父类中的普通链表的一些方法对外不可见.同时,增加尾指针,方便尾操作.
2. isEmpty(), isFull()方法仍然需要对外可见. 但private继承使得他们不可见,这里采用重新定义这两个函数来实现.C++中,子类如果与父类有同样的函数,该函数在父类中没有定义为virtual,则父类该函数被隐藏.不过我们可以在子类中使用作用域运算符来明确指出调用父类的对应方法. 这个使用在后面的.cpp文件中有用到.
3. 析构函数调用的顺序. 在测试代码中,当调用到delete LinkQueue时,首先会触发LinkQueue的析构函数,LinkQueue的析构函数中会释放QueueLinkList,这将触发QueueLinkList的析构函数调用,由于QueueLinkList是LinkList的子类,所以之后会触发LinkList的析构函数的调用.在内存释放的时候要特别小心,对每个指针判断NULL,否则容易造成重复释放内存而导致程序崩溃.
4. 测试代码对该队列进行了1000*100000共计10亿次进出操作,可以看到内存使用在一定范围内波动(入队列内存占用增加,出队列内存占用降低),最终全部释放掉,没有内存泄露发生.
template <typename T, const unsigned int capacity>
class QueueLinkList : private LinkList<T, capacity>
{
public:
QueueLinkList();
~QueueLinkList();
bool enqueueAtTail(T data);
bool dequeueAtFirst(T& data);
bool isEmpty();
bool isFull();
//bool getHead(T& data);
private:
LinkNode<T> *tail = NULL;
};
template<typename T, unsigned int capacity>
class LinkQueue
{
public:
LinkQueue();
~LinkQueue();
bool enQueue(T data);
bool deQueue(T& data);
bool isEmpty();
bool isFull();
private:
//void insert(LinkQueueNode<T> *linkQueueNode, LinkQueueNode<T> *refPtr, LinkQueueNode<T> *priorPtr);
QueueLinkList<T, capacity> *linkList = NULL;
};
对应的源文件如下:
template
template<typename T, unsigned int capacity>
LinkQueue<T, capacity>::LinkQueue()
{
if (NULL == linkList)
{
linkList = new QueueLinkList<T, capacity>();
}
}
template<typename T, unsigned int capacity>
LinkQueue<T, capacity>::~LinkQueue()
{
cout << "LinkQueue destructor called" << endl;
if (isEmpty())
{
if (NULL != linkList)
{
delete linkList;
linkList = NULL;
}
}
else
{
T data;
while (!isEmpty())
{
bool rs = deQueue(data);
//cout << "use desturctor to release the memory. Data=";
//cout << data << endl;
if (!rs)
{
//Need Log fatal error
cout << "fatal error! dequeue failed in destructor!" << endl;
break;
}
}
if (NULL != linkList)
{
delete linkList;
linkList = NULL;
}
}
}
template<typename T, unsigned int capacity>
bool LinkQueue<T,capacity>::isEmpty()
{
bool rs = false;
rs = linkList->isEmpty();
return rs;
}
template<typename T, unsigned int capacity>
bool LinkQueue<T, capacity>::isFull()
{
bool rs = false;
rs = linkList->isFull();
return rs;
}
template<typename T, unsigned int capacity>
bool LinkQueue<T,capacity>::enQueue(T data)
{
bool rs = false;
if (isFull())
{
rs = false;
}
else
{
rs = linkList->enqueueAtTail(data);
}
return rs;
}
template<typename T, unsigned int capacity>
bool LinkQueue<T, capacity>::deQueue(T& data)
{
bool rs = false;
if (isEmpty())
{
rs = false;
}
else
{
rs = linkList->dequeueAtFirst(data);
}
return rs;
}
最后,附上测试代码:
void testLinkQueue()
{
int loopTime = 0;
while (loopTime < 1000)
{
loopTime++;
LinkQueue<int, 100000> *linkQueue = new LinkQueue<int, 100000>();
int data = -1;
int i = 0;
int totalBreak = 0;
while (i < 100000)
{
//if (10 == totalBreak)
//{
// break;
//}
linkQueue->enQueue(i);
//cout << i << endl;
i++;
//_sleep(10000);
//while (i > 10000)
//{
// linkQueue->deQueue(data);
// if (linkQueue->isEmpty())
// {
// totalBreak++;
// i = 0;
// break;
// }
//}
}
delete linkQueue;
linkQueue = NULL;
}
}