list是一个双向链表,为了满足半开半闭区间性质,还添加了一个用来标志的尾节点。
list迭代器
list插入和接合操作不会造成原迭代器失效,而在vector中是行不通的;而不能向vector用原生指针做为迭代器,因为不能直接用++操作。看下list迭代器的结构设计,成员函数都挺简单的(++ ,--,==,->啥的),就不贴上来了
struct _List_iterator_base {
typedef size_t size_type; // list迭代器类型所占字节数
typedef ptrdiff_t difference_type; // 1.区间
typedef bidirectional_iterator_tag iterator_category; // 2.迭代器类型
_List_node_base* _M_node; // 普通指针,指向list的节点
};
template<class _Tp, class _Ref, class _Ptr>
struct _List_iterator : public _List_iterator_base {
// 用来初始化迭代器,主要用在construct里
typedef _List_iterator<_Tp,_Tp&,_Tp*> iterator;
typedef _List_iterator<_Tp,const _Tp&,const _Tp*> const_iterator;
typedef _List_iterator<_Tp,_Ref,_Ptr> _Self;
typedef _Tp value_type; // 3....
typedef _Ptr pointer; // 4....
typedef _Ref reference; // 5.....
typedef _List_node<_Tp> _Node;
};
list类
list缺省使用alloc做为空间配置器,并据此定义了一个list_node_allocator,更方便地以节点大小为配置单位。
template <class _Tp, class _Alloc = __STL_DEFAULT_ALLOCATOR(_Tp) >
class list : protected _List_base<_Tp, _Alloc> {
// requirements:
__STL_CLASS_REQUIRES(_Tp, _Assignable);
typedef _List_base<_Tp, _Alloc> _Base;
protected:
typedef void* _Void_pointer;
public:
typedef _Tp value_type;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef _List_node<_Tp> _Node;
typedef size_t size_type;
typedef ptrdiff_t difference_type; // 为什么容器也要有 区间类型 呢?
typedef simple_alloc<_List_node<_Tp>, _Alloc> _Alloc_type; // 定义于_List_base
typedef typename _Base::allocator_type allocator_type;
allocator_type get_allocator() const { return _Base::get_allocator(); }
public:
typedef _List_iterator<_Tp,_Tp&,_Tp*> iterator;
typedef _List_iterator<_Tp,const _Tp&,const _Tp*> const_iterator;
};
list的Sort():STL算法sort(),只接收RAI,因此list需定义自己的sort()方法,sort函数用到了splice,merge,它们又都是基于transefer函数的。
template <class _Tp, class _Alloc>
void list<_Tp, _Alloc>::sort()
{
// Do nothing if the list has length 0 or 1.
if (_M_node->_M_next != _M_node && _M_node->_M_next->_M_next != _M_node) {
list<_Tp, _Alloc> __carry;
list<_Tp, _Alloc> __counter[64];
int __fill = 0;
while (!empty()) {
// 把当前链表的第一个元素放到carry的头部
__carry.splice(__carry.begin(), *this, begin());
int __i = 0;
// 这个wihle循环是精华,crray不断和counter[0]、counter[1]...去合并
// 假设和counter[0]成功合并,由于i<file,结果是counter[0]为空,结果保存到carry列表
// 这时和counter[1]成功合并,由于i==file,结果是carry为空,结果保存到counter[1]
// 至于设置i<fill 这个条件,是考虑合并的效率吗?
// 但从这个循环可以看出:第i个counter链表最多容纳2^(fill-1)个元素
while(__i < __fill && !__counter[__i].empty()) {
// 将两个递增列表合并,合并后仍然递增
__counter[__i].merge(__carry);
// 将carry链表交换给counter[i],carry为空
__carry.swap(__counter[__i++]);
}
__carry.swap(__counter[__i]);
if (__i == __fill) ++__fill;
}
// 将所有counter列表合并
for (int __i = 1; __i < __fill; ++__i)
__counter[__i].merge(__counter[__i-1]);
swap(__counter[__fill-1]);
}
}
tip:transefer(position,first,last)