9-顺序容器

顺序容器
  • 顺序容器:删除和添加代价高,非顺序进行访问代价高;
  • 常用的顺序容器:
    • vector:可变大小数组,快速随机访问,但是元素随机插入代价高;
    • deque:双向队列,支持快速随机访问,在头尾删除添加元素很快;
    • list:双向列表,支持双向顺序访问,,插入删除速度很快;
    • forward_list:单向列表,支持单向顺序访问,任意位置,添加删除都很快;
    • arry:固定大小数组,支持随机访问,不能够添加和删除元素;
    • string:和vector相似的容器,随机访问速度快,尾部添加删除速度快;
    • 通常情况下,使用vector使最好的选择;
  • 关于选用容器的一些建议:
    • 强烈建议使用vector,除非有更好的选择;
    • 如果程序包含很多小元素,并且额外的开销很大,不要使用list或者forward_list;
    • 如果程序要求随机访问,则应该使用vector或者deque;
    • 如果程序要求在中间插入或者删除元素,应该使用list或者forward_list;
    • 如果程序知识在容器的头尾插入或者删除元素,但是不会再中间插入或者删除元素,应该使用deque;
    • 顺序容器几乎可以保存任意类型的元素,任意类型的含义是这种类型必须包含默认的构造函数,如果是一个没有默认构造函数的类型,就需要这声明:vector<
      NoDefau> v1(10,init)
      ,其中Init表示是用来提供元素初始化容器;
  • 迭代器

    • 如果一个迭代器提供某种操作,那么所有提供相同操作的迭代器对这个操作的实现方式都是相同的;
    • forward_list容器类型部支持递减运算符;
    • 迭代器的范围使用beginend来表示;
    • 几种重要的类型:
    • const_iterator:可以读取元素,但是不能够修改迭代器的类型;
    • size_type:此种容器最大可能容器的大小;
    • difference_type:带符号类型,用于保存两个迭代器之间的类型;
    • value_type:表示元素类型;
    • reference:元素的左值类型,与value_type&类型相同;
    • beginend成员:用于生成第一个元素的位置,以及最后一个元素的下一个位置,以r开头的表示反向迭代器,c开头的表示const迭代器;
    • 当不需要执行写访问时,应该使用cbegincend来进行访问;
    • 容器的定义和初始化:

      • 每个人都定义了一个默认的构造函数,除了arry以外,其他容器的默认构造函数都会指定一个指定类型的容器,并且可以接受容器大小和元素初始值;
      • 将一个容器作为另一个容器的拷贝:

        • 直接拷贝整个容器:Type C1(C2); Type C1=C2;
        • 或者可以使用迭代器制定拷贝的范围,但是arry是不可以执行迭代器拷贝的;
        • 为了一个容器创建另一个容器的拷贝时,两个容器的类型和元素类型必须匹配,当传递迭代器参数来拷贝一个范围时,就不需要容器类型时相同的;
        • 将一个容器初始化为另一个容器的拷贝时,两个容器的类型和元素类型必须相同;
        • 容器的另一种初始化方式:deque<string> authors(authors.begin(),it);
      • 列表初始化:

        • list<string> authors={"Lixun","Linux","element"},支持列表初始化;
        • 只有顺序容器的构造函数才能接受大小参数,关联容器并不支持;
          • 标准库array除了需要指定容器的类型,还需要指定容器的大小,例如:array<int,42>;
          • 由于大小是array类型的一部分,array不支持普通的容器类型构造函数;
          • 默认构造的array是非空的,包含了与其大小一样多的元素;
          • array可以进行拷贝或者进行对象的赋值操作;
          • 在进行拷贝或者对象赋值时,初始值的类型必须与要创建的容器的类型相同,同样的array还要求元素的类型和大小都一样,因为大小也是
            array类型的一部分;
      • 赋值和swap:
        • 赋值运算符表示的是将左边容器中的全部元素替换为右边容器元素的拷贝;
        • 其中标准库类型array也允许进行赋值操作,但是array要求左右两边类型必须相等;
        • swap()是用来交换两个对象的元素,并且要求两个对象具有相同的类型,并且swap()通常具有快的多;
        • 赋值运算符会导致指向左边容器内部的迭代器,引用和指针失效,通常swap()交换内容不会导致容器的迭代器,引用和指针失效,通常容器类型
          arraystring的情况除外;
        • assign:
          • assign()仅适用于顺序容器,但是array并不能够使用;
          • assign允许我们从一个不同但是相容的类型进行赋值,或者从一个容器的子序列进行赋值;
          • 需要注意的是传递给assign的迭代器不能指向调用的容器;
        • swap
          • swap用于交换两个像同类型的容器,swap交换的并不是元素本身,而交换的是内部的数据结构;
          • swap除了array以外,swap不对任何元素进行拷贝,删除或者插入操作,可以保证交换时间在常数时间内部完成;
          • array在执行swap交换的是本身的各个元素,时间的复杂度和元素数目成正比;
      • 容器大小的相关操作:
        • empty():size()为0时,返回值为true;
        • max_size():返回一个大于或者等于该容器所能容纳的最大元素的数值;
        • forward_list:支持max_size()empty(),但是不支持size()操作;
      • 关系运算符
        • 等于:如果两个容器具有相同的大小并且所有元素对应相等,则两个容器相等,否则不想等;
        • 小于:较小容器中的每个元素都等于较大容器;
        • 其他:如果两个元素的之间的元素没有关系,那么比较结果取决于第一个不想等元素的结果;
      • 顺序容器的常用操作

        • 向一个vector,string,deque,掺入元素时,会导致指向容器的迭代器,指针和引用失效;
        • 将元素插入vector,deque,string中的任何位置都是合法的,但是时间复杂度会比较高;
        • 范围掺入元素:
          • 例如:sevc.insert(sevc.end(),10,"Anna"),也就是元素可以按照范围进行插入;
          • insert的返回值表示的是掺入元素之前的位置,所以可以使用这个返回值来循环执行push_front()操作;
        • 访问元素:
          • 迭代器end()指向的是容器尾元素之后的元素;
          • 对于空容器调用frontback是严重的错误;
          • 在容器中访问元素的成员函数,front,back,at和下表,返回的都是引用,如果容器是一个const对象,那么返回的就是const引用;
          • 对于空对象使用下表运算符是不合法的;
        • 删除元素
          • 删除deque中除了首尾之外的任何元素都会使所有的迭代器,引用和指针失效;
          • 同样的删除vector,string某个元素之后的迭代器,引用和指针都会失效;
          • 删除元素的成员函数同样的不见查参数,在删除元素之前,不许保证元素的位置是存在的;
          • 不能够删除空容器;
          • clear()用于删除容器里面的所有元素;
          • 改变容器的大小:array是不能够改变容器的大小的;
          • 如果resize缩小容器,那么指向被删除元素的迭代器,引用和指针都会失效;对vector,stringdeque进行resize可能导致迭代器,
            指针和引用失效;
      • 需要注意的几点:

        • 如果容器是vector或者string,如果存储空间重新被分配,那么指向容器的迭代器,指针和引用都会失效.如果空间没有重新分配,那么指向插入元
          素之后位置的指着,引用和迭代器就会失效;
        • 对于deque来说,插入到首尾之外的任何位置,都会导致迭代器,指针和引用失效,在首尾插入元素,导致迭代器失效,引用和指针有效;
        • 对于listforward_list,迭代器,指针和引用都有效;
        • 删除元素需要注意的是:
          • 对于listforward_list,指向容器其他位置的迭代器,引用和指针都有效;
          • 对于deque,如果再首尾之外的任何位置删除元素,那么指向被删除外其他元素的迭代器,引用或者指针也会失效,如果删除为元素,尾迭代器会失
            效;如果删除首元素,不会被影响;
          • 对于vectorstring来说,指向被删除元素之前的指针,迭代器和引用依然有效;
          • 当删除元素之后的迭代器就会失效;
        • 如果再一个循环中插入/删除deque,string或者vector中的元素,不要缓存end返回的迭代器;
      • vector()对象是如何增长的:
        • vector将元素按照顺序连续存储,vector容器空间的分配策略不是按照每添加一个元素就增加一个元素的策略,而是按照2^n的策略进行增长;
        • capacity():容器不在扩张内存的情况下可以容纳多少各元素;
        • reserve():通知容器它应该准备保留多少个元素;
        • reserve():并不改变容器中元素的数量,仅仅能够影响vector预先分配多大的内存空间,容器的大小是不能够自动减小的;
        • shrink_to_fit():可以用于退回内存空间;
  • string的构造方法
    • string s(cp,n):s里面的内容表示的是cp里面,前n个字符的拷贝;
    • string s(s2,pos):s里面表示的是从下表pos2开始的字符的拷贝;pos < s2.size();
    • string s(s2,pos1,len2):s表示的是2pos2复制len2字符的长度;
    • substr:表示的是原始字符的拷贝;
      • s.substr(pos,n):表示的含义是从pos开始复制n个字符;
      • 如果不传递pos,那么默认就会从0开始复制n个字符;
    • append():表示在一个字符串的末尾添加一些字符串;
    • replace():表示的是将字符串里面的某些字符进行替换;
  • 容器适配器
    • 三个容器顺序适配器:stack(),queuepriority_queue;
    • 容器,迭代器和函数都有适配器,适配器的含义是事某个事物的行为看起来更像另一个事物一样;
    • 对于适配器来说,需要定义两个构造函数,默认的构造函数用于创建一个空对象, 接受一个容器的构造函数拷贝该容器来初始化适配器;
    • 所有的适配器都要求容器具有添加和删除元素的能力;
    • 适配器构造的要求:
      • 适配器不能够构造在array之上;
      • 适配器不能够构造在forward_list之上;
      • 所有的适配器都要求容器具有添加,删除以及访问元素的能力;
      • stack只要求具有push_back(),pop_back()以及back()操作,可以使用array(),forward_list()之外的所有类型来构造stack();
      • queue()适配器要求具有back(),push_back(),front(),push_front(),因此可使用list或者deque来进行构造;
      • priority_queue:除了要求front,push_back()以及pop_back之外,还要求具有随机访问能力,因此可以构造于vector或者deque之上,但是不
        能够基于list构造;
      • 栈适配器:
        • s.pop():表示删除栈顶元素,但是并不饭hi该元素的值;
        • s.push(item):创建一个新的元素,然后压入栈顶;
        • s.top():返回栈顶元素,但是不讲元素弹出;
      • 队列适配器:
        • deque默认是基于queue实现,priority_queue默认是基于vector实现
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值