LIST概述
相对于vector的连续性空间,list就要复杂的多,它的好处是每次插入或删除一个元素,就配置或释放一个元素空间。因此,list对于空间的运用有绝对的精准性,一点也不浪费。而且,对于任何位置的元素插入或元素移除,list永远是常数时间。
list和vector是两个最常被使用的容器,什么情况下最适合使用哪一种容器,就要看元素的多或寡,元素的构造复杂度以及元素的存取行为的特性而定。
LIST的结点
list本身和list的节点是不同的结构,需要分开设计。
如list的节点结构:
template<class T>
struct list_node
{
typedef void* void_pointer;
void_pointer pre;
void_pointer next;
T data;
};
//显然是一个双向的链表
list的迭代器
list不再能像vector一样以普通指针作为迭代器,因为其节点不保证在存储空间中连续存在。list迭代器必须有能力指向list的节点,并有能力进行正确的递增、递减、取值、成员存取等操作。既指递增时指向下一个节点,递减时指向上一个节点,取值时取的是节点的数据值,成员取用时取用的是节点的成员。
由于STL list是一个双向的链表(double linked-list),迭代器必须具备前移、后移的能力,所以list提供的是Bidirectional lterators( 双向迭代器)。
除此之外,list有一个重要性质:插入操作insert和结合操作splice都不会造成原有的list迭代器失效。这在vector是不成立的,因为vector的插入操作可能造成极记忆体重新配置,导致原有的迭代器全部失效。甚至list的元素删除操作erase,也只有“指向被删除元素”的那个迭代器失效,其它迭代器不受任何影响。
LIST迭代器的设计
template<class T,class Ref, class Ptr>
struct _list_iterator
{
typedef _list_iterator<T,T&,T*> iterator;
typedef _list_iterator<T,Ref,Ptr> self;
typedef bidirectional_iterator_tag iterator_category;
typedef T value_type;
typedef Ptr pointer;
typedef Ref reference;
typedef _list_node<T>* link_type;
typedef size_t size_type;
typedef ptrdiff_t difference;
link_type node;//迭代器内部普通指针,指向list的节点
//constructor
_list_iterator(link_type x) : node(x){}
_list_iterator(){}
_list_iterator(const iterator& x) : node(x.node) {}
bool operator==(const self& x) const{return node==x.node;}
bool opterator!=(const self& x) const{return node!=x.node;}
//取节点的数据值
reference opterator*() const {return (*node).data;}
//迭代器的成员存取运算子的标准做法
pointer operator->() const {return &(opertaor*());}
//对迭代器累加1,就是前进一个节点
self& operator++()
{
node=(link_type)((*node).next);
return *this;
}
self operator++(int)
{
self tmp=*this;
++*this;
return tmp;
}
//对迭代器递减1,就是后退一个节点
self& operator--()
{
node=(link_type)((*node).pre);
return *this;
}
self operator--(int)
{
self tmp=*this;
--*this;
return tem;
}
};
LIST的数据结构