单链表实现的队列。
#ifndef _QUEUE_USE_SINGLE_LINKED_LIST_H_
#define _QUEUE_USE_SINGLE_LINKED_LIST_H_
/*********************************************************
算法导论:10.2-3 使用单链表实现一个队列
使用单链表实现一个队列,在队列的尾部插入元素,在队列的头部删除元素,
dequeue 操作,向链表中最后插入元素,为了提高效率,可以提供一个指向链表
尾部的指针,这样就无需每次都要遍历链表;enqueue 操作将链表的第一个元素删除。
enqueue 和 dequeue 操作运行时间为 O(1)。
**********************************************************/
#include <stdexcept>
template <class T>
class QueueUseSinglyLinkedList{
public:
// 一个表示链表结点的数据结构
class Node{
public:
// 只有 QueueUseSinglyLinkedList 才可以构造这个类型的对象
// 访问这个类型的私有成员
friend class QueueUseSinglyLinkedList < T > ;
// 结点的值
T value;
private:
// 默认构造函数,要求类型 T 也要有默认构造函数
Node() = default;
// 将构造函数设置为私有的,防止在外部创建这个类型的对象
Node(const T& e) :_next(nullptr), value(e){}
// 指向下一个元素
Node* _next;
};
// 分别在默认构造函数和析构函数中分配和释放头指针指向的内存空间
// 初始头指针和尾指针相同
QueueUseSinglyLinkedList() { _tail = _head = new Node(); }
~QueueUseSinglyLinkedList();
// 队列的 enqueue 操作
void enqueue(const T&);
// 队列的 dequeue 操作
T dequeue();
// 测试队列是否为空,只需要测试头结点的 _next 是否指向一个空的结点。
inline bool empty()const{ return (nullptr == _head->_next); }
private:
// 链表头结点的指针,指向链表的第一个元素。
Node* _head;
// 链尾的指针,指向链表的最后一个结点的前的一个节点
Node* _tail;
};
template <class T>
void QueueUseSinglyLinkedList<T>::enqueue(const T& element){
// 构造一个结点
Node* node = new Node(element);
_tail->_next = node;
_tail = node;
}
template <class T>
T QueueUseSinglyLinkedList <T>::dequeue(){
// 如果队列为空,则抛出异常
if (empty())
throw underflow_error("queue empty");
Node* node = _head->_next;
T value = node->value;
_head->_next = node->_next;
// 释放出队列元素的空间
delete node;
return value;
}
template <class T>
QueueUseSinglyLinkedList<T>::~QueueUseSinglyLinkedList(){
// 将链表中元素占用的空间释放
Node* node = _head->_next;
while (node)
{
Node *n = node->_next;
delete node;
node = n;
}
// 释放头结点占用的空间
delete _head;
}
#endif