队列
队列:队列是一种仅仅能在线性表两端操作的数据结构。
队列头部(front):取出数据的一端。
队列尾部(rear): 插入数据的一端。
队列的特性:先进先出。
继承关系:
Queue.h
/* * Queue: 队列接口 * 成员函数: * add() 在队尾(rear)插入一个元素。进队列 * remove() 删除队列头部(front)的一个元素。出队列。 * front() 返回队列头部的元素 * clear() 清空整个队列 * length() 返回队列元素的个数 */ #ifndef QUEUE_H #define QUEUE_H #include"TopClass.h" namespace DSL { template <typename T> class Queue : public TopClass { public: virtual void add(const T& obj) = 0; virtual void remove() = 0; virtual T front() const = 0; virtual void clear() = 0; virtual int length() const = 0; }; } #endif
队列的顺序存储的实现:使用循环数组作为存储空间。首元素为零,最大尾元素为容量减一。
StaticQueue.h
/* * StaticQueue: 静态循环数组实现队列 * 成员变量: * m_space[] 队列存储空间,T是数组成员变量类型,N是数组长度 * m_front 队头标识符 * m_rear 队尾标识符,指向真实队尾的下一个元素,方便于判断队列是否满或空 * m_length 队列实时长度 * 成员函数: * StaticQueue() 初始化成员变量 * add() 插入元素到队尾 * remove() 删除队头元素 * front() 返回队头元素 * clear() 清空成员变量 * length() 返回实时队列长度 * ~StaticQueue() */ #ifndef STATICQUEUE_H #define STATICQUEUE_H #include"Queue.h" #include"Exception.h" namespace DSL { 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& obj) { if(m_length < N) { m_space[m_rear] = obj; 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 element to remove from the queue!"); } } T front() const { if(m_length > 0 && m_length <= N) { return m_space[m_front]; } else { THROW_EXCEPTION(InvalidOperationException,"no element to get from the queue!"); } } int length() const { return m_length; } void clear() { m_length = 0; m_front = 0; m_rear = 0; } ~StaticQueue() { clear(); } }; } #endif /* Test int main(void) { 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; } */
缺点:数组元素为类类型是,创建StaticQueue对象时,会多次调用元素类型的构造函数。
队列的链式存储的实现:组合单链表,继承队列。链表头是队列头,链表尾是队列尾。链表头部出数据,链表尾部入数据。
继承关系图:
LinkListqueue.h
缺点:插入时间复杂度为 O(n)
队列的双向循环链表的实现:采用Linux内核链表。
继承关系图:
LinkListQueue.h
/* * LinkListQueue: 单链表队列 * 成员变量: * LinkList<T> m_LinkList: 组合使用单链表类来实现队列 * 成员函数: * LinkListQueue * add() 在队列尾部添加数据(单链表尾部) * remove() 在队列头部取出数据(单链表头部) * front() 取出队列头部数据(单链表头部) * clear() 清除所有数据(清空单链表) * length() 返回队列长度(返回单链表长度) * ~LinkListQueue() 清空队列(清空单链表) */ #ifndef LINKLISTQUEUE_H #define LINKLISTQUEUE_H #include"LinkList.h" #include"Queue.h" namespace DSL { template <typename T> class LinkListQueue : public Queue<T> { protected: LinkList<T> m_LinkList; public: LinkListQueue() { } void add(const T& obj) { m_LinkList.insert(obj); } void remove() { if(m_LinkList.length() > 0) { m_LinkList.remove(0); } else { THROW_EXCEPTION(InvalidOperationException,"error: no element to remove!"); } } T front() const { if(m_LinkList.length() > 0) { m_LinkList.get(0); } else { THROW_EXCEPTION(InvalidOperationException,"error: no element to get!"); } } int length() const { return m_LinkList.length(); } void clear() { m_LinkList.clean(); } ~LinkListQueue() { clear(); } }; } #endif