List作为STL的代表链表的容器,相信大家都不会陌生。本文将讨论一个List容器的一个主流实现。
STL List容器在底层一般是用(双链表)double-linked list来实现的,管理着一个又一个的结点。如果你有双链表的基础知识,那么这篇文章对你来说应该不会太难。与vector一样,List容器采用了普遍的内存管理器allocator来管理内存,维护着底层的双链表的表头和表尾,从而轻松实现了STL容器的相关操作。List的插入和删除实质上就是双链表的插入和删除。
让我们来看看实现的源码吧。本文采用的是SGI的一个STL实现。
编译环境为VS2008.
template <class T> struct __list_iterator;
template <class T> struct __list_const_iterator;
List的结点,双链表的节点一般包含一个指向前一个结点和后一个结点的指针。
template <class T>
struct __list_node {
typedef void* void_pointer;
void_pointer next; // 指向下一个节点的指针
void_pointer prev; // 指向前一个节点的指针
T data; //list 数据
};
list 的iterator的实现。list的iterator封装了对list节点的访问的实现。可以进行自增和自减,从而可以对list进行遍历。iterator是访问list元素的基本单元。
template<class T>
struct __list_iterator {
//常用的typedef。
typedef __list_iterator<T> iterator;
typedef __list_const_iterator<T> const_iterator;
typedef T value_type;
typedef value_type* pointer;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef __list_node<T>* link_type;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
//数据成员, 类型为__list_node<T>*
link_type node; //数据成员 ,为一个节点的指针。
// 构造函数
__list_iterator(link_type x) : node(x) {} //用一个结点来 初始化一个iterator
//默认构造函数
__list_iterator() {}
//比较iterator是否相等
bool operator==(const iterator& x) const { return node == x.node; }
bool operator!=(const iterator& x) const { return node != x.node; }
//*操作符,使得访问iterator就像访问一个指针
reference operator*() const { return (*node).data; }
//自增操作符. ++
iterator& operator++() {
node = (link_type)((*node).next); //使iterator包含的是下一个节点
return *this;
}
//后置自增,c++标准为了区分前置自增和后置自增,在后置自增的参数列表里加了int,实际调用的时候 不 必给参数赋值。int起的只是一个占位符的功能。请注意后置自增的实现。
iterator operator++(int) {
iterator tmp = *this;
++*this; //这里利用了前置自增的实现。从这个函数的实现里可以发现前置自增和后置自增的语义区别
return tmp;
}
//自减操作符 --
iterator& operator--() {
node = (link_type)((*node).prev);
return *this;
}
//自减操作符,后置--
iterator operator--(int) {
iterator tmp = *this;
--*this; //看前置自减和后置自减的区别。
return tmp;
}
};
list的const_iterator的实现,const_iterator语义上属于只读的迭代器。不能修改其指向的节点包含的数据成员的值。
template<class T>
struct __list_const_iterator {
//一些typedef
typedef __list_iterator<T> iterator;
typedef __list_const_iterator<T> const_iterator;
typedef T value_type;
typedef value_type* pointer;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef __list_node<T>* link_type;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
//数据成员
link_type node;
//构造函数
__list_const_iterator(link_type x) : node(x) {}
__list_const_iterator() {}
//拷贝构造函数
__list_const_iterator(const iterator& x) : node(x.node) {}
//比较操作符
bool operator==(const const_iterator& x) const { return node == x.node; }
bool operator!=(const const_iterator& x) const { return node != x.node; }
//只读间访,不能修改data的值
const_reference operator*() const { return (*node).data; }
//前置自增,使得该迭代器指向下一个结点
const_iterator& operator++() {
node = (link_type)((*node).next);
return *this;
}
//后置自增,使得该迭代器指向下一个节点,并返回当前节点的迭代器
const_iterator operator++(int) {
const_iterator tmp = *this;
++*this;
return tmp;
}
//自减,使该迭代器指向前一个结点
const_iterator& operator--() {
node = (link_type)((*node).prev);
return *this;
}
//后置自减
const_iterator operator--(int) {
const_iterator tmp = *this;
--*this;
return tmp;
}
};
由以上迭代器的实现可以知道,自增和自减的实现均利用了节点所维护的指向前一个节点和后一个节点的指针。他们的实现很简单。list容器维护头迭代器和尾迭代器。和尾迭代器就够了。
让我们来看看list的声明吧:
template <class T >
class list {
typedef alloc Alloc;
protected:
typedef void* void_pointer;
typedef __list_node<T> list_node;
typedef simple_alloc<list_node, Alloc> list_node_allocator; //内存分配器
public:
//一些typedefs
typedef T value_type;
typedef value_type* pointer;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef list_node* link_type;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
protected:
//创建一个空的结点(分配内存)
link_type get_node() { return list_node_allocator::allocate(); }
//销毁一个结点
void put_node(link_type p) { list_node_allocator::deallocate(p); }
protected:
link_type node; // list的end(). (*node).prev 指向begin.
size_type length; //维护着list的长度。
public:
typedef __list_iterator<T> iterator; // 迭代器
typedef __list_const_iterator<T> const_iterator; //只读迭代器
typedef reverse_bidirectional_iterator<const_iterator, value_type,
const_reference, difference_type> // 反向迭代器,在另外一个文件中 定义
const_reverse_iterator;
typedef reverse_bidirectional_iterator<iterator, value_type, reference,
difference_type>
reverse_iterator;
public:
//默认构造函数,创建一个空的list
list() : length(0)
{
node = get_node();
(*node).next = node;
(*node).prev = node;
}
//返回list的头节点
iterator begin() { return (link_type)((*node).next); }
const_iterator begin() const { return (link_type)((*node).next); }
//返回list的末节点。注意,末节点是最后一个元素的下一个节点。末节点不包含元素的值
iterator end() { return node; }
const_iterator end() const { return node; }
//反向迭代器
reverse_iterator rbegin() { return reverse_iterator(end()); }
const_reverse_iterator rbegin() const {
return const_reverse_iterator(end());
}
reverse_iterator rend() { return reverse_iterator(begin()); }
const_reverse_iterator rend() const {
return const_reverse_iterator(begin());
}
//判断是否为空
bool empty() const { return length == 0; }
// 返回list的长度
size_type size() const { return length; }
// 返回list的最大长度, 4294967295
size_type max_size() const { return size_type(-1); }
//返回list的头部 值引用
reference front() { return *begin(); }
const_reference front() const { return *begin(); }
//返回list的末尾 值的引用
reference back() { return *(--end()); }
const_reference back() const { return *(--end()); }
//交换两个list的内容。很高效
void swap(list<T /*, Alloc*/>& x) {
::swap(node, x.node); //交换node的值。这里默认list的allocator是相同的。不同的allocator的list是不同类型的,不能交换
::swap(length, x.length); //交换长度。
}
//在指定iterator之前插入新结点
iterator insert(iterator position, const T& x) {
link_type tmp = get_node(); //分配一个新结点
construct(&((*tmp).data), x); // 将该新结点的数据赋值为x
(*tmp).next = position.node; // 在position之前插入该结点
(*tmp).prev = (*position.node).prev;
(*(link_type((*position.node).prev))).next = tmp;
(*position.node).prev = tmp;
++length; //长度加1
return tmp; //返回新插入的结点
}
// 插入系列的函数
iterator insert(iterator position) { return insert(position, T()); } //在position之前 插入默认的T
void insert(iterator position, const T* first, const T* last); //插入一个range的值
void insert(iterator position, const_iterator first, const_iterator last);
void insert(iterator position, size_type n, const T& x); //在position之前 插入n个值为x的结点
//在头部插入一个元素
void push_front(const T& x) { insert(begin(), x); }
//在尾部插入一个元素
void push_back(const T& x) { insert(end(), x); }
//删除一个结点
void erase(iterator position) {
(*(link_type((*position.node).prev))).next = (*position.node).next;// 将该迭代器指向的结点删除
(*(link_type((*position.node).next))).prev = (*position.node).prev;
destroy(&(*position.node).data);
put_node(position.node);
--length; //长度减1
}
// 由此可见list的插入和删除都是常数时间的。
//删除系列的函数声明
void erase(iterator first, iterator last); //删除一个区间的结点
//调整list的长度
void resize(size_type new_size, const T& x);
void resize(size_type new_size) { resize(new_size, T()); }
// 清空一个list的所有元素
void clear();
//删除头部元素
void pop_front() { erase(begin()); }
//删除尾部元素
void pop_back() {
iterator tmp = end();
erase(--tmp);
}
//构造函数,创建一个长度为n,每个元素值均为value的list
list(size_type n, const T& value) : length(0) {
node = get_node();
(*node).next = node;
(*node).prev = node;
insert(begin(), n, value);
}
// 构造函数,创建一个长度为n,值均为T的默认值的list
list(size_type n) : length(0) {
node = get_node(); // 构造node
(*node).next = node;
(*node).prev = node;
insert(begin(), n, T());
}
//区间构造函数
list(const T* first, const T* last) : length(0) {
node = get_node(); // 构造node
(*node).next = node;
(*node).prev = node;
insert(begin(), first, last);
}
//区间构造函数
list(const_iterator first, const_iterator last) : length(0) {
node = get_node();
(*node).next = node;
(*node).prev = node;
insert(begin(), first, last);
}
//拷贝构造函数
list(const list<T /*, Alloc*/>& x) : length(0) {
node = get_node();
(*node).next = node;
(*node).prev = node;
insert(begin(), x.begin(), x.end());
}
//析构函数
~list() {
clear();
put_node(node);
}
list<T /*, Alloc*/>& operator=(const list<T /*, Alloc*/>& x);
protected:
//支持函数,交换三个节点
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;
}
}
public:
//拼接函数
void splice(iterator position, list<T /*, Alloc*/>& x) {
if (!x.empty()) {
transfer(position, x.begin(), x.end());
length += x.length;
x.length = 0;
}
}
//拼接函数
void splice(iterator position, list<T /*, Alloc*/>& x, iterator i) {
iterator j = i;
if (position == i || position == ++j) return;
transfer(position, i, j);
++length;
--x.length;
}
//拼接函数
void splice(iterator position, list<T /*, Alloc*/>& x, iterator first, iterator last) {
if (first != last) {
if (&x != this) {
difference_type n = 0;
distance(first, last, n);
x.length -= n;
length += n;
}
transfer(position, first, last);
}
}
//删除某一个值
void remove(const T& value);
// 删除重复的值
void unique();
//merge另外一个list
void merge(list<T /*, Alloc*/>& x);
// 倒序
void reverse();
//排序
void sort();
};
以上是list的声明以及部分函数的实现。
其余函数的实现将在下一篇文章中讨论。