1 概述
STL list是个双向链表。SGI STL另提供了一个单向链表(single linked list),名为slist。
它和list的主要区别在与slist的迭代器属于单向的Forward Iterator,后者的迭代器属于双向的Bidirectional Iterator。
它和list的共同具有的一个特点:它们的插入、移除、接合等操作不会造成原有迭代器的失效。
根据STL的习惯,插入操作一般会将新元素插入指定位置之前,而非之后。然而对于单向链表,它无法方便地回头定出前一个位置,因此必须从头找起。所以除了slist起点处附近的区域外,在其他位置上采用insert或erase操作,都属于不智之举。为此,slist提供insert_after()和erase_after()供灵活运用。
基于同样的(效率)考虑,slist不提供push_back(),只提供push_front()。因此slist的元素次序会和元素插入进来的次序相反。
2 slist的节点和迭代器
节点结构:
struct __slist_node_base {
__slist_node_base* next;
};
template<class T>
struct __slist_node : public __slist_node_base {
T data;
}
迭代器结构:
//...
template<class T, class Ref, class Ptr>
struct __slist_iterator : publi __slist_iterator_base {
//...
typedef __slist_node<T> list_node;
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;
}
//没有实现operator--,因为是一个forward iterator
}
3 slist的数据结构
template <class T, class Alloc = alloc>
class slist {
//...
private:
//...
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 destory_node(list_node* node) {
destory(&node->data); //析构元素
list_node_allocator::deallocator(node); //释放空间
}
//...
public:
iterator begin() { return iterator((list_node*)head.next); }
iterator end() {return iterator(0); }
};
4 slist的元素操作