目录
1、队列的概念及实现
队列是一种特殊的线性表
队列仅能在线性表的两端进行操作
-队头(Front) : 取出数据元素的一端
-队尾(Rear) : 插入数据元素的一端
队列的特性
-先进先出(First In First Out)
队列的操作
-创建队列( Queue() )
-销毁队列( ~Queue() )
-清空队列( clear() )
-进队列( add() )
-出队列( remove() )
-获取队头元素( front() )
-获取队列的长度( length() )
队列的实现
//Queue.h
#ifndef QUEUE_H
#define QUEUE_H
#include "Object.h"
namespace DTLib
{
template <typename T>
class Queue : public Object
{
public:
virtual void add(const T& e) = 0;
virtual void remove() = 0;
virtual T front() const = 0;
virtual void clear() = 0;
virtual int length() const = 0;
};
}
#endif // QUEUE_H
2、基于顺序存储结构的队列
队列的顺序实现
StaticQueue设计要点
-使用原生数组作为队列的存储空间
-使用模板参数决定队列的最大容量
StaticQueue实现要点(循环计数法)
-关键操作
进队列: m_space[m_rear] = e; m_rear = (m_rear + 1) % N;
出队列: m_front = (m_front + 1) % N;
-队列的状态
队空: (m_length == 0) && (m_front == m_rear)
队满: (m_length == N) && (m_front == m_rear)
3、编程实验
基于顺序存储结构的队列 StaticQueue.h
#ifndef STATICQUEUE_H
#define STATICQUEUE_H
#include "Queue.h"
#include "Exception.h"
namespace DTLib
{
template <typename T, int N>
class StaticQueue : public Queue<T>
{
protected:
T m_space[N]; //当前队列存储空间
int m_front; //队头标识
int m_rear; //队尾标识
int m_length; //当前队列长度
public:
StaticQueue()
{
m_front = 0;
m_rear = 0;
m_length = 0;
}
void add(const T& e)
{
if(m_length < N)
{
m_space[m_rear] = e;
m_rear = (m_rear + 1) % N;
m_length++;
}
else
{
THROW_EXCEPTION(InvalidOperationException, "No space in current queue ...");
}
}
void remove()
{
if(m_length > 0)
{
m_front = (m_front + 1) % N;
m_length--;
}
else
{
THROW_EXCEPTION(InvalidOperationException, "No space in current queue ...");
}
}
T front() const
{
if(m_length > 0)
{
return m_space[m_front];
}
else
{
THROW_EXCEPTION(InvalidOperationException, "No space in current queue ...");
}
}
void clear()
{
m_front = 0;
m_rear = 0;
m_length = 0;
}
int length() const
{
return m_length;
}
int capacity() const
{
return N;
}
};
}
#endif // STATICQUEUE_H
main.cpp
#include <iostream>
#include "StaticQueue.h"
using namespace std;
using namespace DTLib;
int main()
{
StaticQueue<int, 5> queue;
for(int i = 0; i < 5; i++)
{
queue.add(i);
}
while(queue.length() > 0)
{
cout << queue.front() << endl;
queue.remove();
}
return 0;
}
4、基于链式存储结构的队列
队列的链式存储实现
链式队列的设计要点
-类模板,抽象父类Queue的直接子类
-在内部使用链式结构实现元素的存储
-只在链表的头部和尾部进行操作
链式队列的设计要点
5、编程实验
基于LinkList的队列 LinkQueue.h
#ifndef LINKQUEUE_H
#define LINKQUEUE_H
#include "Queue.h"
#include "LinkList.h"
#include "Exception.h"
namespace DTLib
{
template <typename T>
class LinkQueue : public Queue<T>
{
protected:
LinkList<T> m_list;
public:
LinkQueue()
{
}
void add(const T& e) //O(n)
{
m_list.insert(e);
}
void remove() //O(1)
{
if(m_list.length() > 0)
{
m_list.remove(0);
}
else
{
THROW_EXCEPTION(InvalidOperationException, "No element in current queue ...");
}
}
T front() const //O(1)
{
if(m_list.length() > 0)
{
return m_list.get(0);
}
else
{
THROW_EXCEPTION(InvalidOperationException, "No element in current queue ...");
}
}
void clear() //O(n)
{
m_list.clear();
}
int length() const //O(1)
{
return m_list.length();
}
};
}
#endif // LINKQUEUE_H
会发现基于单链表的链式队列并不高效(对比)
队列链式存储实现的优化
链式队列的设计优化
6、编程实验
基于Linux内核链表的队列 LinkQueue.h
#ifndef LINKQUEUE_H
#define LINKQUEUE_H
#include "Queue.h"
#include "LinuxList.h"
#include "Exception.h"
namespace DTLib
{
template <typename T>
class LinkQueue : public Queue<T>
{
protected:
struct Node : public Object
{
list_head head;
T value;
};
list_head m_header;//头结点
int m_length;//当前队列长度
public:
LinkQueue()
{
m_length = 0;
INIT_LIST_HEAD(&m_header);
}
void add(const T& e) //O(1)
{
Node* node = new Node();
if( node )
{
node->value = e;
list_add_tail(&node->head, &m_header);
m_length++;
}
else
{
THROW_EXCEPTION(NoEnoughMemoryException, "No memory to add new element ...");
}
}
void remove() //O(1)
{
if(m_length > 0)
{
list_head* toDel = m_header.next;
list_del(toDel);
m_length--;
delete list_entry(toDel, Node, head);
}
else
{
THROW_EXCEPTION(InvalidOperationException, "No element in current queue ...");
}
}
T front() const //O(1)
{
if(m_length > 0)
{
return list_entry(m_header.next, Node, head)->value;
}
else
{
THROW_EXCEPTION(InvalidOperationException, "No element in current queue ...");
}
}
void clear() //O(n)
{
while(m_length > 0)
{
remove();
}
}
int length() const
{
return m_length;
}
~LinkQueue() //O(n)
{
clear();
}
};
}
#endif // LINKQUEUE_H
7、小结
队列是一种特殊的线性表,具有先进先出的特性
队列只允许在线性表的两端进行操作,一端进,一端出
StaticQueue使用原生数组作为内部存储空间
StaticQueue的最大容量由模板参数决定
StaticQueue采用循环计数法提高队列操作的效率
StaticQueue在初始化时可能多次调用元素类型的构造函数
LinkList的组合使用能够实现队列的功能,但是不够高效
LinkQueue的最终实现组合使用了Linux内核链表
LinkQueue中入队和出队操作可以在常量时间内完成