顺序容器相关操作与知识

1.顺序容器概述

一个容器就是一些特定类型对象的集合。顺序容器为程序员提供了控制元素存储和访问顺序的能力。这种顺序不依赖于元素的值,而是与元素加入容器时的位置相对应。

vector可变大小数组。支持快速随机访问,在尾部之外的位置插入或删除元素可能很慢
deque双端队列。支持快速随机访问,头尾位置插入删除速度块,不支持在中间插入
list双向链表。只支持双向顺序访问,在list中任何位置进行插入、删除操作速度都很快,需要额外的空间
forward_list单向链表。只支持单向顺序访问,在任何位置进行插入、删除操作速度都很快,也需要额外空间
array固定大小数组。支持快速随机访问。不能添加或删除元素
string与vector相似,在尾部插入删除速度快

通常使用vector容器是最好的选择

新版的容器比旧版的容器快很多

大家可以思考一下:list和forward_list 和 vector和deque 容器的使用场景

容器库概览:

一般来说,每个容器都定义在一个头文件中,文件名与类型名相同。

顺序容器几乎可以保存任意类型的元素。


顺序容器构造函数的一个版本接受容器大小的参数,他使用了元素类型的默认构造函数。但某些类没有默认构造函数。我们可以定义一个保存这种类型对象的容器,但我们在构造这种容器时不能只传递给它一个元素数目参数:

vector<noDefault> v1(10,init); //正确示范,init 提供了元素初始化器

2.迭代器

所有容器的一个接口

begin和end 指向迭代器的首和尾

first和last 是指向第一个元素和最后一个元素的下一个位置

  • 如果begin和end相等,则范围为空

  • 如果begin和end不等,则范围至少包含一个元素,且begin指向该范围中的第一个元素

  • 我们可以对begin递增若干次,使得begin == end

vector<int> ::value_type x;

value_type 就是将x返回一个容器的类型,我们就无须考虑容器内容到底是什么类型了。

reference 引用 绑定元素的引用

反向迭代器

reverse_iterator

迭代器版本有:iterator、reverse_iterator、const_iterator、const_reverse_iterator

当不需要写访问时,应该使用cbegin和cend

容器定义和初始化

每个容器都定义了一个默认构造函数。除array之外,其他容器的默认构造函数都会创建一个指定类型的空容器,且都可以接受指定容器大小和元素初始值

array和内置数组的区别

与内置数组一样,标准库array的大小也是类型的一部分。当定义一个array时,除了指定元素类型,还要指定容器大小:

例如:array<int,42> array<string,10>

为了使用array类型,我们必须同时指定元素类型和大小:

array<int,10>::size_type i; //数组类型包括元素类型和大小

array<int>::size_type j; array<int> 不是一个类型

array的优势?

array可以进行赋值,但是内置数组不可以

3.赋值和swap

将一个容器初始化为另一个容器的拷贝

  • 可以直接拷贝整个容器

  • 拷贝一个迭代器对指定的元素范围

对于容器的直接拷贝,先看容器是否匹配,再看容器类型是否匹配,如果不匹配,就可以用元素范围来赋值

swap函数

swap只是交换了两个容器的内部数据结构,array外,swap不对任何元素进行拷贝、删除或插入操作,因此可以保证在常数时间内完成。

元素不会被移动的事实,意味着,除string以外,指向容器的迭代器、引用和指针在swap操作之后都不会失效。他们仍指向swap操作之前所指向的那些元素。但是,在swap之后这些元素就属于不同的容器了。

容器初始化为另一个容器的拷贝时,两个容器的容器类型和元素类型都必须相同。

assign函数

赋值运算符要求左边和右边的运算对象具有相同的类型。它将右边运算对象中所有元素拷贝到左边运算对象中。assign允许我们从一个不同但相容的类型赋值,或者从容器的一个子序列赋值。

list<string> names; vector<const char*> oldstyle;names = oldstyle; names.assign(oldstyle.cbegin(),oldstyle.cend());

4.容器大小与关系

优先级的结合性!

5.顺序容器的操作

push_back; 压入一个值

push_front;在头部压入

insert;插入值

emplace;创建一个值

svec.insert(svec.begin(),"hello");

使用insert插入函数 插入头部

forward_list 有自己的insert和emplace版本;

forward_list 没有back函数 也不能递减forward迭代器

向一个vector、string或deque插入元素会使所有指向容器的迭代器、引用和指针失效。

容器元素是拷贝

访问元素

如果容器中没有元素,访问操作的结果是未定义的。

为了获取尾元素,必须首先递减此迭代器。另一个重要之处是,在调用front和back之前,要确保容器非空,否则可能会报错

at和下标操作只适用于string、vector、deque、array

在容器中访问元素的成员函数(front、back、下标和at)返回的都是引用,也就是说我们可以通过返回值来修改里面的值,如果不想被修改那么需要返回一个const值

当我们使用下标时,一定要注意合法性,不要超出范围

删除元素

pop_front和pop_back成员函数分别删除首元素和尾元素。与vector和string不支持push_front一样,这些类型也不支持pop。如果容器为空,那么也不能支持这些操作

erase函数

erase函数是用于删除容器中的元素的成员函数,比如std::vector、std::list等。erase函数通常返回指向删除元素之后的第一个元素的迭代器,或者返回一个迭代器指示容器末尾(如果删除的是最后一个元素)。具体返回值

erase可以从容器内部删除一个元素或一部分元素

list.erase(list.begin(),list.end());删除list中的全部元素

assign(ia,ia+11); 拷贝函数内容

特殊的forward_list操作

数据结构中的单向链表!

当添加或删除一个元素时,删除或添加的元素之前的那个元素的后继会发生改变。为了添加或删除一个元素,我们需要访问前驱,以便改变前驱的连接。

forward_list因此定义了insert_after/emplace_after和_erase_after的操作,为了支持这些操作,forward也定义了before_begin,它返回一个首前迭代器。第一个元素前面的指针

取决于容器类型和erase函数的重载版本。

注意各个函数的返回值,值得注意的是插入的返回值就是当前插入点,删除指向删除的下一个元素

例如:

6.改变容器大小

我们可以使用resize来增大或缩小容器,与往常一样,array不支持resize

list<int> ilist(10,42);

ilist.resize(15); 添加五个值为0的值

ilist.resize(25,-1);增加10个为-1的值

ilist.resize(5);删除后20个元素

如果元素类型是类类型,我们必须提供初始值,或者类必须有默认构造函数

改变容器大小的时候,考虑之前的指针是否失效!

当迭代器发生改变时,一定记得重新定义迭代器,强烈建议使用erase和insert函数,因为这两个函数有返回值,使用起来方便和安全。

7,vector对象是如何增长的

shrink_to_fit(); 将capacity减少为与size()相同大小

capacity(); 不重新分配内存空间的话,c可以保存多少元素

reserve(n);分配至少能容纳n个元素的内存空间

reserve并不改变容器中的元素的数量,它仅影响vector预先分配多大的内存空间。如果需求大小小于或者等于当前容量,reserve什么也不做。

capacity和size的区别

capacity是在不分配新的内存空间的前提下它最多可以保存多少元素,而size是指它已经保存的元素数量

每个vector实现都可以选择自己的内存分配策略。但是必须遵守的一条原则是:只有当迫不得己时才可以分配新的内存空间。

8.额外的string构造方法

类似于范围复制

substr操作

返回一个string,他是原始string的一部分或全部的拷贝。可以传递给substr一个可选的开始位置和计数值。

改变string的一些方法,类似前面提及的改变其他容器的函数,例如assign、insert、erase

s.insert(s.size(),5,'!'); //在s末尾插入5个感叹号

s.erease(s.size()-5,5); //从s删除最后五个字符

s.assign(cp,7); 用cp中的内容替换s的内容

append 追加函数

s2.append(" hello");

replace替换函数

s2.replace(11,3,"5th"); 从11的位置开始,删除三个字符,替换成5th

string类的搜索

string类提供了6个不同的搜索函数,每个函数都有4个重载版本。每个搜索都返回一个string::size_type的值,表示匹配发生位置的下标,如果搜索失败返回一个名为string::npos的static的成员。

find函数完成最简单的搜索,查找参数指定字符串,若找到,则返回第一个匹配位置的下标,否则返回npos,区分大小写

string name("AnnaBelle");

auto pos1 = name.find("Anna"); // pos1 == 0;

find_first_of与find_first_not_of函数

string numbers("0123456789"),name("r2d2");

auto pos = name.find_first_of(numbsers); 返回1,即name中的第一个数字的下标

string dept("03714p3");

auto pos = dept.find_first_not_of(numbers); 返回5,字符‘p'的下标

find_first_of函数在实际应用中的使用很常用

compare函数

除了关系运算符外,标准库string类型还提供了一组compare函数,这些函数与C标准库的strcmp函数很相似。类似strcmp,根据s是等于、大于、小于参数指定的字符串,s.compare返回0、正数或负数。

数值转换

string可以与其他类型相互转换 接触的不多

9.容器适配器

stack和queue,关于容器适配器,就是该容器是基于其他类型的容器生成的,例如stack和queue适配器是根据deque容器生成的

使用容器适配器和使用普通的容器用法差不多,只是函数稍有区别

stack适配器

stack类型定义在stack头文件中,pop删除栈顶元素,不返回该元素值。

push压入一个元素到栈顶

emplace(args) 由args构造

s.top() 返回栈顶元素,但不删除元素

queue适配器

queue和priority_queue适配器定义在queue头文件中。

同样的,pop是返回首元素值,删除该元素

front返回首元素或尾元素

back只适用于queue

top返回最高优先元素,但不删除

push压入一个元素到末尾,而priority_queue中恰当的位置创建一个元素

q.emplace 创建一个元素

  • 29
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值