slist:单向链表(single linked list)
slist与双向链表的主要差别在于,前者的迭代器属于forward iterator,后者的迭代器属于bidirectional iterator。单向链表所耗用空间更小,某些操作更快,但一些功能受到限制。
根据STL的习惯,插入操作会将新元素插入于指定位置之前,而作为一个单向链表,slist没有任何方便的办法可以回头定出前一个位置,因此它必须从头找起。也就是说,除了slist起点处附近的区域外,在其它位置采用insert或erase操作函数,都属于不智之举。这就是slist相较于list之下的大缺点。为此slist提供了insert_after()和erase_after()。
基于效率考虑,slist不提供push_back(),只提供push_front()。因此slist的元素次序和元素插入的次序相反。
节点
//单向链表的节点基本结构
struct __slist_node_base
{
__slist_node_base* next;
};
//单向链表的节点结构
template<class T>
struct __slist_node :public __slist_node_base
{
T data;
};
//全局函数,已知某一节点,插入新节点于其后
inline __slist_node_base* __slist_make_link(
__slist_node_base* prev_node,
__slist_node_base* new_node)
{
//令new节点的下一节点为prev节点的下一节点
new_node->next = prev_node->next;
prev_node->next = new_node;//令prev节点的下一节点指向new节点
return new_node;
}
//全局函数,单向链表的大小(元素个数)
inline size_t __slist_size(__slist_node_base* node)
{
size_t result = 0;
for (; node != 0; node = node->next)
++result;//一个一个累计
return result;
}
迭代器
//单向链表的迭代器基本结构
struct __slist_iterator_base
{
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef forward_iterator_tag iterator_category;
__slist_node_base* node;//指向节点基本结构
__slist_iterator_base(__slist_node_base* x):node(x){}
void incr() { node = node->next; }
bool operator==(const __slist_iterator_base& x)const {
return node == x.node;
}
bool operator!=(const __slist_iterator_base& x)const {
return node != x.node;
}
};
//单向链表的迭代器结构
template<class T,class Ref,class Ptr>
struct __slist_iterator:pulic __slist_iterator_base
{
typedef __slist_iterator<T, T&, T*> iterator;
typedef __slist_iterator<T, const T&, const T*> const_iterator;
typedef __slist_iterator<T, Ref, Ptr> self;
typedef T value_type;
typedef Ptr pointer;
typedef Ref reference;
typedef __slist_node<T> list_node;
__slist_iterator(list_node* x):__slist_iterator_base(x){}
//调用slist<T>::end()时会造成__slist_iterator(0),于是调用上述函数
__slist_iterator() :__slist_iterator_base(0) {}
__slist_iterator(const iterator& x):__slist_iterator_base(x){}
reference operator*()const { return ((list_node*)node)->data; }
pointer operator->()const { return &(operator*()); }
self& operator++() {
incr();
return *this;
}
self operator++(int) {
self tmp = *this;
incr();
return tmp;
}
//因为是一个forward iterator所以没有operator--
};
比较两个slist迭代器是否等同时,由于__slist_iterator并未对operator==进行重载,所以会调用__slist_iterator_base::operator==,故两个slist迭代器是否等同,看其__slist_node_base* node是否等同而定。
数据结构
template<class T,class Alloc=alloc>
class slist
{
public:
typedef T value_type;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef __slist_iterator<T, T&, T*> iterator;
typedef __slist_iterator<T, const T&, const T*> const_iterator;
private:
typedef __slist_node<T> list_node;
typedef __slist_node_base<T> llist_node_base;
typedef __slist_iterator_base iterator_base;
typedef simple_alloc<list_node, Alloc> list_node_allocator;
static list_node* create_node(const value_type& x) {
list_node* node = list_node_allocator::allocate();
__STL_TRY{
construct(&node->data,x);
node->next = 0;
}
__STL_UNWIND(list_node_allocator::deallocate(node));
return node;
}
static void destroy_node(list_node* node) {
destroy(&node->data);
list_node_allocator::deallocate(node);
}
private:
list_node_base head;//头部,注意,它不是指针,是实物
public:
slist() { head.next = 0; }
~slist() { clear(); }
public:
iterator begin() { return iterator((list_node*)head.next); }
iterator end() { return itertor(0); }
size_type size()const { return __slist_size(head.next); }
bool empty()const { return head.next == 0; }
//两个slist互换,只需要将head交换互指即可
void swap(slist& L)
{
list_node_base* tmp = head.next;
head.next = L.head.next;
L.head.next = tmp;
}
public:
//取头部元素
reference front() { return ((list_node*)head.next)->data; }
//从头部插入元素(新元素成为slist的第一个元素
void push_front(const value_type& x)
{
__slist_make_link(&head, create_node(x));
}
//没有push_back()
//从头部取走元素(删除之),修改head
void pop_front() {
list_node* node = (list_node*)head.next;
head.next = node->next;
destroy_node(node);
}
//...
};