list的节点结构:
template <class T>
struct __list_node {
typedef void* void_pointer;
void_pointer next;
void_pointer prev;
T data;
};
List不能像vector那样以普通的指针作为iterator,因为节点不能保证内存在空间上是连续的。
List是一个双向链表,所以需要有前移后移的功能,所以list提供的Bidirectional_iterator迭代器。
list的最重要性质就是insert操作和接合操作(splice)都不会造成list迭代器失效,这在vector上是不成立的。list的删除只会导致指向被删除元素的那个迭代器失效,其他迭代器不会失效。
// list的迭代器设计
template<class T, class Ref, class Ptr>
struct __list_iterator {
typedef __list_iterator<T, T&, T*> iterator;
typedef __list_iterator<T, const T&, const T*> const_iterator;
typedef __list_iterator<T, Ref, Ptr> self;
typedef bidirectional_iterator_tag iterator_category; // Bidirectional_iterator型别迭代器
typedef T value_type;
typedef Ptr pointer;
typedef Ref reference;
typedef __list_node<T>* link_type; // iterator内部的link类型是指针类型
typedef size_t size_type;
typedef ptrdiff_t difference_type;
link_type node; // 迭代器内部指向node的指针
__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 operator!=(const self& x) const { return node != x.node; }
// 一下对迭代器取值,取得是节点的data
reference operator*() const { return (*node).data; }
#ifndef __SGI_STL_NO_ARROW_OPERATOR
pointer operator->() const { return &(operator*()); }
#endif /* __SGI_STL_NO_ARROW_OPERATOR */
self& operator++() {
node = (link_type)((*node).next);
return *this;
}
// 前进一个节点
self operator++(int) {
self tmp = *this;
++*this;
return tmp;
}
self& operator--() {
node = (link_type)((*node).prev);
return *this;
}
self operator--(int) {
self tmp = *this;
--*this;
return tmp;
}
};
template <class T, class Alloc = alloc> // 和vector一样默认使用alloc作为内存配置器
class list {
protected:
typedef __list_node<T> list_node;
typedef list_node* link_type;
...
protected:
link_type node; // 只要一个指针就表示了整个环状的双向链表
};
整个list的示意图,只要刻意在环状链表的尾端加上一个空白节点,变符合stl规范的“前闭后开”[first, last )区间的规范,
这样几个函数变很容易的实现了
iterator begin() { return (link_type)((*node).next); }
iterator end() { return node; }
bool empty() const { return node->next == node; }
size_type size() const {
size_type result = 0;
distance(begin(), end(), result);
return result;
}
//取得是节点的内容(元素值)list_iterator中operator*()取得是节点的data
reference front() { return *begin(); }
//注意iterator是前开后闭区间,所有是*--end()是最后一个元素的内容
reference back() { return *(--end()); }
对以list的结构有很清晰了解之后,相信对于list的使用就很简单了
另外补充一点:
// list内部(非公开接口)提供了迁移操作,将某些连续范围[first, last)的元素迁移到某个特定位置position之前,技术上也很简单就是指针的移动
// 其他很多复杂的操作如splice(接合,将连续范围的元素从一个list移动到另外一个list的某个点),sort,merge, reverse等等操作都是在这个基础上实现
// STL算法sort只接受RamdonAccessIterator,所以list实现了一个自己sort member function.采用的是quick sort
void transfer(iterator position, iterator first, iterator last) {
if (position != last) {
(*(link_type((*last.node).prev))).next = position.node;
(*(link_type((*first.node).prev))).next = last.node;
(*(link_type((*position.node).prev))).next = first.node;
link_type tmp = link_type((*position.node).prev);
(*position.node).prev = (*last.node).prev;
(*last.node).prev = (*first.node).prev;
(*first.node).prev = tmp;
}
}
// 逆向重置reverse,使用transfer很简单的实现了o(n)
// 其算法核心是历遍链表, 每次取出一个结点, 并插入到链表起始点
// 历遍完成后链表满足倒置
template <class T, class Alloc>
void list<T, Alloc>::reverse() {
if (node->next == node || link_type(node->next)->next == node) return;
iterator first = begin();
++first;
while (first != end()) {
iterator old = first;
++first;
transfer(begin(), old, first);
}
}