链式队列是基于单链表的一种存储表示, 其形状如下图所示:
(队列的队头指针指向单链表的第一个结点, 队尾指针指向单链表的最后一个结点, 注意没有无用的空[头/尾]节点)
用单链表表示的链式队列特别适合于数据元素变动比较大的情况, 而且不存在队列满而产生溢出的情况;
链式队列结点构造:
[这次我们将节点构造成了类LinkQueue的嵌套类]
struct ChainNode { ChainNode(const Type &_data, ChainNode *_next = NULL) :data(_data), next(_next) {} Type data; ChainNode *next; };
链式队列构造:
template <typename Type> class LinkQueue { template <typename T> friend ostream &operator<<(ostream &os, LinkQueue<T> &queue); public: LinkQueue(); ~LinkQueue(); bool isEmpty() const; void push(const Type &data); void pop(); //返回队首元素 const Type &front() const; //返回队尾元素 const Type &back() const; //清空队列 void makeEmpty(); private: struct ChainNode { ChainNode(const Type &_data, ChainNode *_next = NULL) :data(_data), next(_next) {} Type data; ChainNode *next; }; private: ChainNode *m_front; //队首指针[注意不是指向一个无用的空节点] ChainNode *m_back; //队尾指针[注意不是指向一个无用的空节点] };
队列的构造与析构:
template <typename Type> LinkQueue<Type>::LinkQueue() { m_front = m_back = NULL; } template <typename Type> LinkQueue<Type>::~LinkQueue() { makeEmpty(); }
队列的四大操作:
//入队, 这是链式队列的关键 template <typename Type> void LinkQueue<Type>::push(const Type &data) { if (isEmpty()) { //如果队列为空 //则队首与队尾指针共同指向一个新构造的对象 m_front = m_back = new ChainNode(data); } else { //首先让队尾的下一位置指向一个新构造的对象 m_back->next = new ChainNode(data); //然后队尾指针后移 m_back = m_back->next; } }
//出队 template <typename Type> void LinkQueue<Type>::pop() { if (isEmpty()) throw std::range_error("queue is empty"); ChainNode *deleteNode = m_front; // 队首指针后移 m_front = m_front->next; delete deleteNode; }
//取队首元素 template <typename Type> const Type &LinkQueue<Type>::front() const { if (isEmpty()) throw std::range_error("queue is empty"); return (m_front->data); }
//取队尾元素 template <typename Type> const Type &LinkQueue<Type>::back() const { if (isEmpty()) throw std::range_error("queue is empty"); return (m_back->data); }
清空队列与判空操作:
template <typename Type> void LinkQueue<Type>::makeEmpty() { while (!isEmpty()) { pop(); } }
template <typename Type> bool LinkQueue<Type>::isEmpty() const { return (m_front == NULL); }
输出队列所有元素(以做测试):
template <typename Type> ostream &operator<<(ostream &os, LinkQueue<Type> &queue) { for (typename LinkQueue<Type>::ChainNode *currentNode = queue.m_front; currentNode != NULL; currentNode = currentNode->next) { os << currentNode->data << ' '; } return os; }
附-测试代码:
int main() { LinkQueue<int> queue; for (int i = 0; i < 10; ++i) { queue.push(rand()%100); } cout << queue << endl; cout << queue.front() << endl; queue.pop(); cout << queue.front() << endl; cout << queue.back() << endl; cout << queue << endl; LinkQueue<char> cQueue; cQueue.push('A'); cout << "cQueue.front = " << cQueue.front() << endl; cout << "cQueue.back = " << cQueue.back() << endl; cQueue.pop(); cout << cQueue << endl; try { cout << "cQueue.front = " << cQueue.front() << endl; cout << "cQueue.back = " << cQueue.back() << endl; } catch(const std::exception &e) { cerr << e.what() << endl; } return 0; }