STL学习----入门(1)[list]



接着上面:

#include<list>:

// <list>

template < class T, class Alloc = allocator<T> > class list;

列表(List)是一个允许在序列中任何一处位置以常量耗时插入或删除元素且可以双向迭代的顺序容器(Sequence container)。

A list is a sequence container that supports bidirectional iterators and allows constant time insert and erase operations anywhere within the sequence, with storage management handled automatically.

容性特性:

顺序序列

顺序容器中的元素按照严格的线性顺序排序。可以通过元素在序列中的位置访问对应的元素。

双向链表

容器中的每个元素保存了定位前一个元素及后一个元素的信息,允许在任何一处位置以常量耗时进行插入或删除操作,但不能进行直接随机访问(Direct random access)。

能够感知内存分配器的(Allocator-aware)

容器使用一个内存分配器对象来动态地处理它的存储需求。

  • T

    存储在容器中的元素的数据类型。

    在类模板内部,使用其别名为 value_type 的成员类型。

    Alloc

    容器内部用来管理内存分配及释放的内存分配器的类型。

    这个参数是可选的,它的默认值是 std::allocator<T>,这个是一个最简单的非值依赖的(Value-independent)内存分配器。 在类模板内部,使用其别名为 allocator_type 的成员类型。

  • 标准模板库(Standard Template Library,简称STL)中的列表容器采用的是双向链表(Doubly-linked lists)数据结构。双向链表可以保存以不同且无关的储存位置容纳的元素。元素间的顺序是通过各个元素中指向前一个元素的链接及指向后一个元素的链接等联系维护的。

    C++11 该特点跟 std:: forward_list 容器的有点相似:主要的区别就是 std:: forward_list 是一个单向链表,因此它只能被正向迭代( Iterated forward),以换取更小更高效的特点。

    增加或移动列表中的元素不会使指向它们的指针、引用、迭代器失效,只有当对应的元素被销毁时才会如此。

    你可能会好奇,为什么STL同时提供列表(std::list)跟向量(std::vector)及其它等多种容器,原因是它们的底层实现方式是不一样的,每一种实现方式都有各自的消耗(空间或时间)及优点。

    相比较于其它的基本标准顺序容器(数组 std::array、向量 std::vector、双端队列 std::deque 等),列表通常在容器中已获得迭代器的任意位置处插入、获得(Extracting,提取)、移动元素等操作中表现出更出色的性能,对那些密集使用上述操作的算法,使用列表同样能提升性能,比如排序算法。

    Since lists allow fast insertion and erasing from the middle of a list, certain operations are provided specifically for them.

    C++编程语言国际标准:ISO/IEC 14882:2011

    双向链表(std::list)及正向链表(std:: forward_list C++11)相比于其它顺序容器的主要缺点是它们不能够通过元素在容器中的位置直接访问(Direct access)元素。举个例子:如果想访问一个列表中的第六个元素,那么就必须从一个已知位置(比如开头或末尾)处开始迭代,这会消耗与两个位置之间距间相关的线性时间。而且它们还为保存各个元素间的链接信息消耗更多额外的内存(这点对由小尺寸元素组成的大列表尤为明显)。

    在定义一个列表对象时,所有你需要做的就是给出保存在列表中的元素的类型(更多定义方式可以参考 list::list 成员函数)。举个例子,下述代码定义了一个整数列表:

        
        
    1. std::list<int> integer_list;

    模板类中提供了成员函数 push_front 及 push_back,你可以分别用它们在列表头或尾插入一个新的元素。举个例子:

        
        
    1. std::list<int> integer_list;
    2.  
    3. integer_list.push_front(1);
    4. integer_list.push_front(2);

    这个例子创建了一个列表,其中有两个元素,元素 1 及之后的元素 2。

    C++11 开始,你也可以使用 emplace_front 及 emplace_back 分别向列表头或尾插入一个新的元素。

    相对地,你也可以通过使用模板类提供的 pop_frontpop_back 成员函数来分别删除第一个或最后一个元素。单独地使用其中的部份函数,就能很容易的创建基于列表的队列(Queue)或栈(Stack)等数据结构,当然,最好还是使用由标准模板库提供的容器适配器 std::stackstd::deque

    快速的在容器中间部份插入元素是列表的最大优势。可以使用成员函数 insert 完成这一操作:需要指定插入的元素及指向插入位置的迭代器(新的元素将会插入到当前所指向元素的前面)。从 C++11 开始,你也可以使用 emplace 来完成这一操作,具体区别请查看两个函数的详细介绍。以下是 list::insert 的声明:

        
        
    1. iterator insert(iterator position, const T& element_to_insert);

    其中迭代器可以按以下方式定义:

        
        
    1. list<type>::iterator iterator_name; // type要替换成元素的具体类型

    所要注意的是标准模板库中的列表同时支持正向(Forward)及反向(Reverse)迭代(因为它是基于双链表实现的)。

    使用 insert 及 end 函数可以实现 push_back (及 push_front)的功能:

        
        
    1. std::list<int> integer_list;
    2. integer_list.insert(integer_list.end(), item);

    正如所料的,list 类模板包含了由标准容器定义的 sizeempty 函数。这里有一点必须要注意:size 函数的时间复杂度为 O(n)(从 C++11 开始,时间复杂度变为 O(1))。所以,如果你想简单判断一个列表是否为空,可以使用 empty 而不是 检查它的大小是否为 0。如果希望保证当前列表是空的,可以使用 clear 函数。具体例子如下:

        
        
    1. std::list<int> foo;
    2. // 会让人困惑,即使C++11有所改进
    3. if(foo.size() == 0)
    4. ...
    5. // 推荐的方法
    6. if(foo.empty())
    7. ...
    8.  
    9. foo.clear();
    10. // 现在,foo 是一个空列表

    可以使用 sort 成员函数对列表进行排序,该操作时间复杂度保证为 O(nlogn)。

    注意,标准库中提供的 std::sort 排序函数需要容器支持随机访问迭代器,而 list 模板类并未提供该支持(直接原因是 list 提供的迭代器不支持 operator- 操作符函数),所以 std::sort 不支持对 list 的排序。

    sort 函数的代码示例:

        
        
    1. foo.sort();

    可以使用 reverse 成员函数来反转列表。标准C++库的算法库中存在一个相似的函数:std::reverse,该函数同样用于反转容器中的元素。当前成员函数(list::reverse)与 std::reverse 的区别就是调用 list::reverse 后不会影响其它正在使用的迭代器所指向的值。

    reverse 成员函数的代码示例:

        
        
    1. foo.reverse()

    可以使用 unique 成员函数来“唯一化”元素。该函数删除容器中的所有连续重复元素,仅仅留下每组等值元素中的第一个元素。比如,有如下元素组成列表:

    1 1 8 9 7 8 2 3 3

    在调用 unique 后,剩余的元素为:

    1 8 9 7 8 2 3

    注意上述结果中,仍然有两个 8:仅仅删除连续的等值元素。如果希望一个元素在序列中仅仅出现一次,你需要先排序这个列表。具体例子如下:

        
        
    1. std::list<int> int_list;
    2. int_list.push_back(1);
    3. int_list.push_back(1);
    4. int_list.push_back(8);
    5. int_list.push_back(9);
    6. int_list.push_back(7);
    7. int_list.push_back(8);
    8. int_list.push_back(2);
    9. int_list.push_back(3);
    10. int_list.push_back(3);
    11. int_list.sort();
    12. int_list.unique();
    13.  
    14. for(std::list<int>::iterator list_iter = int_list.begin();
    15. list_iter != int_list.end(); list_iter++)
    16. {
    17. std::cout<<*list_iter<<endl;
    18. }
  • 成员类型定义
    value_type第一个模板参数 T
    allocator_type第二个模板参数 Alloc
    size_type无符号整数类型(通常为 size_t
    difference_type有符号整数类型(通常为 ptrdiff_t
    referenceAllocator::reference 已弃用
    value_type& C++11
    const_referenceAllocator::const_reference 已弃用
    const value_type& C++11
    pointerAllocator::pointer 已弃用
    std::allocator_traits<Allocator>::pointer C++11
    const_pointerAllocator::const_pointer 已弃用
    std::allocator_traits<Allocator>::const_pointer C++11
    iterator双向迭代器
    const_iterator常双向迭代器
    reverse_iteratorstd::reverse_iterator<iterator>
    const_reverse_iteratorstd::reverse_iterator<const_iterator>
  • (constructor)创建 list
    (destructor)释放 list
    operator=值赋操作

    Iterators:

    begin返回指向容器起始位置的迭代器(iterator
    end返回指向容器末尾位置的迭代器
    rbegin返回指向容器逆序起始位置的逆序迭代器(reverse_iterator
    rend返回指向容器逆序末尾位置的逆序迭代器
    cbegin C++11返回指向容器起始位置的常迭代器(const_iterator
    cend C++11返回指向容器末尾位置的常迭代器
    crbegin C++11返回指向容器逆序起始位置的常逆序迭代器(const_reverse_iterator
    crend C++11返回指向容器逆序末尾位置的常逆序迭代器

    Capacity:

    empty判断是否为空
    size返回有效元素个数
    max_size返回 list 支持的最大元素个数

    Element access:

    front访问第一个元素
    back访问最后一个元素

    Modifiers:

    assign将新的内容赋值给容器
    emplace_front C++11 在容器开头构造及插入一个元素
    push_front在容器开头插入一个元素
    pop_front删除第一个元素
    emplace_back C++11在容器末尾构造及插入一个元素
    push_back在末尾增加一个元素
    pop_back删除最后一个元素
    emplace C++11构造及插入一个元素
    insert插入元素
    erase删除元素
    swap交换内容
    resize改变有效元素的个数
    clear清空内容

    Operations:

    splice使元素从一个列表移动到另一个列表
    remove删除值为指定值的元素
    remove_if删除满足指定条件的元素
    unique删除重复值
    merge合并已排序的列表
    sort为容器中的所有元素排序
    reverse反转元素的顺序

    Observers:

    get_allocator获得内存分配器
  • operator==、operator!=、operator<、operator<=、operator>、operator>=关系操作符
    std::swap交换两个列表的内容
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值