slist

slist

STL list是个双向链表。SGI STL另提供了一个单向链表,名为slist

slistlist的主要差别在于,前者的迭代器属于单向的 Forward Iterator,后者的迭代器属于双向的Bidirectional Iterator。单向链表所耗用的空间更小,某些操作更快

slistlist共同具有的一个相同特色是,它们的插入,移除,接合操作并不会造成原有的迭代器失效(当然了,指向被移除元素的那个迭代器,在移除操作发生之后肯定是会失效的)。

注意,根据STL的习惯,插入操作会将新元素插入于指定位置之前,而非之后。然而作为一个单向链表,slist没有任何方便的方法可以回头定出一个位置,因此它必须从头找起。换句话说,除了slist起点处附近的区域之外,在其他位置上采用inserterase操作函数,都属不智之举。这就是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);
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值