与
vector 不同,
list 的底层是用
双向链表实现的,其逻辑上连续的元素并不是地址连续的。
list 每插入或删除一个元素,就配置或释放一个元素的空间,内存利用率较高。对于任意位置上元素的插入或删除操作,永远是常数时间。vector 的是O(n) 。
list的节点
template <class T>
struct ListNode {
T data;
ListNode<T> *prev;
ListNode<T> *next;
};
list的迭代器
由于list 是一个双向链表,迭代器必须具备前移、后移的能力,所以list 的迭代器属于Bidirectional Iterator 。 向list 添加元素的操作不会使原有的迭代器失效,而vector 会重新配置空间会导致原有的迭代器失效;list 的删除操作会使“指向被删除元素”的迭代器失效(引用未定义内容),而vector 的指向被删除元素的迭代器会指向被删除元素的下一个元素。
list的结构
SGI list 不仅是一个双向链表,而且还是一个环状双向链表,所以它只需要一个指针,便可表示完整的链表。
为了使list 能满足STL 对前闭后开区间的要求,环状双向链表维护了一个尾空节点。
list::end() 指向的就是尾空节点。 list 为空时,尾空节点的prev 和next 都指向自己。list 对象持有尾空节点的地址。
list的相关操作
insert
本质上,vector 和list 的插入元素操作,都会把新元素插在迭代器position所指的元素的前面,只不过在插入操作完成后,vector 的position 指向了新插入的元素,list 的position 指向原有的元素。
有如下list : 在position 处插入新元素7 会变成这样: vector 的话会是这样: 此外,list 支持push_front 、push_back 、pop_front 、pop_back 、erase 、clear 、remove 、unique 等操作。
transfer
list 内部提供了一个transfer 操作:将某连续范围内的元素迁移到某个特定位置之前。这个函数实现的难点在于指针的移动,它为诸如splice 、merge 、sort 等更复杂的操作奠定了基础。
list 不能使用STL 算法的sort (只接受Random Access Iterator ),所以它自定义了一个sort 成员函数。
|