slist
STL list
是个双向链表。SGI STL
另提供了一个单向链表,名为slist
。
slist
和list
的主要差别在于,前者的迭代器属于单向的 Forward Iterator
,后者的迭代器属于双向的Bidirectional Iterator
。单向链表所耗用的空间更小,某些操作更快。
slist
和list
共同具有的一个相同特色是,它们的插入,移除,接合操作并不会造成原有的迭代器失效(当然了,指向被移除元素的那个迭代器,在移除操作发生之后肯定是会失效的)。
注意,根据STL
的习惯,插入操作会将新元素插入于指定位置之前,而非之后。然而作为一个单向链表,slist
没有任何方便的方法可以回头定出一个位置,因此它必须从头找起。换句话说,除了slist
起点处附近的区域之外,在其他位置上采用insert
或erase
操作函数,都属不智之举。这就是slist
相较于list
的大缺点。为此,slist
提供了insert_after()
和erase_after()
。
slist
不提供push_back()
,只提供push_front()
。因此slist
的元素次序会和元素插入进来的次序相反。
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_node->next = prev_node->next;
prev_node->next = new_node;
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;
}
slist的迭代器
//单向链表的迭代器基本结构
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 : public __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 __list_node<T> list_node;
__slist_iterator(list_node* x) : __slist_iterator_base(x) {}
__slist_iterator() : __slist_iterator_base(0) {}
__slist_iterator(const iterator& x) : __slist_iterator_base(x.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
};
注意,比较两个slist
迭代器是否等同时,由于__slist_iterator
并未对operator==
实现重载,所以会调用__slist_iterator_base::operator==
。根据其中定义,我们知道两个slist迭代器是否相同,要看__slist_node_base* node
是否相同。
slist的数据结构
template<class T, class Alloc = alloc>
class slist
{
public:
typedef T value_type;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef value_type& reference;
typedef const value_type& const_refernece;
tyoedef size_t size_type;
typedef __slist_iterator<T,T&,T*> itertor;
typedef __slist_iterator<T,const T&,const T*> const_iterator;
private:
typedef __slist_node<T> list_node;
typedef __slist_node_base list_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;
}
private:
list_node_base head; //头部,注意,他不是指针,是实物
public:
slist() { head.next = 0; }
~slist() { clear(); }
public:
iterator begin() { return iterator((list_node*)head.next); }
iterator end() { return iterator(0); }
size_type size() const { return __slist_size(head.next); }
bool empty() const { return head.next == 0; }
//两个slist互换,
void swap(slist& L)
{
list_node_base* temp = head.next;
head.next = L.head.next;
L.head.next = tmp;
}
public:
//取头部元素
reference front() { return ((list_node*)head.next)->data; }
//从头部插入元素
void push_front(const value_type& x)
{
__slist_make_link(&head, create_node(x));
}
//没有push_back
void pop_front(){
list_node* node = (list_node*)head.next;
head.next = node->next;
destory_node(node);
}
};