c++标准库——list容器

c++标准库——list容器
四月 9th, 2010 by ewangplay

list容器以双向链表的方式管理它的元素,尽管c++标准没有指定list容器的具体实现,但通常其实现就是基于双向链表结构。

4.1 list容器的能力

list容器的内部结构跟vector和deque都差别巨大,所以list容器在行为特征上跟vector和deque有明显差异:

  • list容器不提供随机元素访问。如果你想访问第五个元素,那么必须先遍历前四个元素才能到达第五个元素。所以使用list容器访问任意元素是低效的。
  • 在list容器的任何位置插入和删除元素的效率都是一样的,都同样高效,这基于list容器的内部结构,不需要移动其他元素,只需要维护相应的指针即可。
  • 插入和删除操作不会使其他元素的引用、指针和迭代器失效。
  • list容器对异常处理有着完美的支持,一个操作要么成功完成,要么对容器不产生任何影响。

跟vector和deque相比,在外部操作接口上list容器有下列区别:

  • list容器既没有[]操作符,也没有at()接口,因为list容器不支持随机元素访问。
  • list容器不提供对capacity和内存维护相关的接口,因为list容器中的每个元素分配自己的内存空间,当元素删除时,其对应的内存空间销毁。
  • list容器额外提供了一些移动元素的接口,这些接口比相应的通用算法要高效,因为它们基于list容器的内部结构而设计,所以在需要时应该优先使用它们。
4.2 list容器的操作

list容器跟vector、deque容器都属于序列容器(sequence containers), 所以大部分的操作接口还是类似的,像创建(create)、复制(copy)、销毁(destroy)、大小(size)、比较(compare)、赋值(assignment)、迭代器(iterator)等都基本类似。

Element Access
因为list容器不支持随机访问,所以元素访问接口只保留了front()和back(),分别用来访问第一个和最后一个元素。同样这两个接口不会检查容器是否为空,如果对一个空的list容器调用这两个接口,结果未可知。

Iterator Functions

跟vector和deque容器类似,list容器也提供了四个获取iterator的接口:begin(), end(), rbegin(), rend()。但是有一个细节上的不同就是vector和deque的迭代器是随机访问迭代器(random access iterator), 而list容器的迭代器是双向迭代器(bidirectional iterator)。它们的区别就是随机访问迭代器可以进行一些算术运算(+, -),而双向迭代器只可以进行递增(++)、递减(--)操作。而且一些通用算法也只接受随机访问迭代器,使用时要注意。


Inserting and Removing Elements
对于插入和删除元素,list容器除了提供所有跟deque一样的接口外,还额外增补了两个删除元素的接口:remove(), remove_if():

  • c.remove(val): 删除容器中所有值为val的元素。
  • c.remove_if(op): 删除容器中所有使op为true的元素。

这两个函数因为根据list容器的内部结构而设计,所以比对应的通用算法要高效,所以在同等的条件下应该优先使用这两个成员函数。


Splice Functions(拼接函数)

对比vector和deque容器,list容器在内部结构上采用了链表结构,这就使得在任意位置插入和删除元素都非常便利,所以list容器额外提供了一组拼接函数,你可以使用这些成员接口在一个容器内部或者两个容器之间方便地移动元素,当然这两个容器要具备相同的类型。

  • c.unique(): 删除容器中值相同位置相邻的额外元素,只保留一个元素。
  • c.unique(op): 删除容器中同时满足op条件位置相邻的额外元素,只保留一个元素。
  • c1.splice(pos, c2): 把容器c2中的所有元素移动到容器c1的迭代器位置pos之前。
  • c1.splice(pos, c2, c2pos): 把容器c2中的c2pos位置的元素移动到容器c1的pos位置之前。(c1和c2可以是同一个容器)
  • c1.splice(pos, c2, c2beg, c2end): 把容器c2中的[c2beg, c2end)范围内的所有元素移动到容器c1的pos位置之前。(c1和c2可以是同一个容器)
  • c.sort(): 以操作符<(升序)来排序容器中所有元素。
  • c.sort(op): 以运算子op来排序容器中所有元素。
  • c1.merge(c2): 假定容器c1和c2包含的元素都已经过排序(sorted with operation < ), 该接口把c2容器中的所有元素移动到c1中并且也按照排序规则排序。
  • c1.merge(c2, op): 假定容器c1和c2包含的元素都已经过排序(sorted with op), 该接口把c2容器中的所有元素移动到c1中并且也按照排序规则排序。
  • c.reverse(): 反序容器中的元素次序。

 

4.3 list容器的异常处理

list容器对异常处理有着几乎完美的支持,几乎所有的操作要么成功完成,要么保持原状。例外的操作就是赋值操作和sort()接口,不能保证这一点,但最低保证不会产生资源泄漏。另外merge(), remove(), remove_if(), unique()接口在元素比较(comparing elements)不抛出异常时保证这一点。

4.4 使用list容器的一个例子
下面我们看一个使用list容器拼接函数的例子:

#include <iostream>
#include <list>
#include <algorithm>
#include "print.hpp"
using namespace std;
int main()
{
    //create tow list set
    list<int> col1, col2;

    //insert some elements into two set
    for (int i = 0; i < 6; ++i) 
    {
        col1.push_back(i);
        col2.push_front(i);
    }

    //print two set
    PRINT_ELEMENTS(col1, "col1: ");
    PRINT_ELEMENTS(col2, "col2: ");

    //move all elements of col1 in front of the first element with value 3 in col2
    col2.splice(find(col2.begin(), col2.end(), 3), col1);

    //print two set
    PRINT_ELEMENTS(col1, "col1: ");
    PRINT_ELEMENTS(col2, "col2: ");

    //move the first element of col2 to the end position
    col2.splice(col2.end(), col2, col2.begin());

    //print two set
    PRINT_ELEMENTS(col1, "col1: ");
    PRINT_ELEMENTS(col2, "col2: ");

    //assign col2 to col1 and unique col2
    col2.sort();
    col1 =  col2;
    col2.unique();

    //print two set
    PRINT_ELEMENTS(col1, "col1: ");
    PRINT_ELEMENTS(col2, "col2: ");

    //merge the col2 to col1
    col1.merge(col2);

    //print two set
    PRINT_ELEMENTS(col1, "col1: ");
    PRINT_ELEMENTS(col2, "col2: ");
}

执行结果如下:

col1: 0 1 2 3 4 5 
col2: 5 4 3 2 1 0 
col1: 
col2: 5 4 0 1 2 3 4 5 3 2 1 0 
col1: 
col2: 4 0 1 2 3 4 5 3 2 1 0 5 
col1: 0 0 1 1 2 2 3 3 4 4 5 5 
col2: 0 1 2 3 4 5 
col1: 0 0 0 1 1 1 2 2 2 3 3 3 4 4 4 5 5 5 
col2: 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值