顺序容器(上)

容器:特定类型对象的集合(模板)
通用操作:CP295(表9.2)
顺序容器:顺序与元素加入容器的位置有关

//可变大小数组
#include <vector>

不能在循环中向vector中添加对象

//与vector相似,专门用于保存字符
#include <string>
//c++11 数组类型(固定大小)
#include <array>          
//c++11 单向链表,,没有size操作
#include <forward_list>   
//双向链表,
#include <list>  
//双端队列
#include <deque>          

容量类型

size_type 
  • 也可用于下标索引,因为编译器不会检查下标是否越界,所以该类型为unsigned可以确保下标不会小于0
  • 只能对已存在的下标运算符执行下标操作

访问:

  • 支持快速随机访问:

    • vector(保存在连续空间)
    • string(保存在连续空间)
    • array
    • deque
  • 支持单向顺序访问:

    • forward_list
  • 只支持双向顺序访问:

    • list

快速插入删除:

  • 任何位置:
    • forward_list
    • list
  • 头尾:
    • deque
  • 尾部:

    • string
    • vector
      (在尾部之外需要移动后面的元素,可能需要额外分配空间)
  • 禁止:

    • array

选用原则:

  1. 相比内置数据结构推荐使用容器
  2. 通常首选vector
  3. 按照程序对数据读写的需求:
    应用中占主导地位的操作决定容器的选择(即当访问和插入删除的要求无法兼容)
    注意当

    1. 只有在读取输入时需要在容器中间位置插入元素
    2. 需要随机访问

    此时

    1. 如果必须要在中间插入,可以先使用list,再将内容拷贝到vector
    2. 如果不是,可以在vector中插入后调用sort函数进行排序

4 无法确定时,选择使用迭代器访问vector和list

这里写代码片

独享操作:CP299(表9.3)
初始化

  • 默认初始化为空容器(除array皆可用)
vector<int> vec;
//当元素类型没有默认构造函数时需要传递初始化器
vector<int> vec(init);     
  • 圆括号:构造(除array皆可用)
vector<int> vec(10);//10个元素
vector<int> vec(10,1);//10个为1的元素
vector<string> vec(10);//错误
  • 花括号:
    • 列表初始化
    • 除array皆可用
    • 只有在无法执行列表初始化的时候才会考虑其他的初始化方式
vector<int> vec{10};//一个为10的元素
vector<int> vec{10,1};//一个为10和为1的元素 
vector<string> vec{ "hi" };
//无法使用列表初始化,尝试使用默认值来初始化
vector<string> vec{10};//10个元素 
vector<string> vec{ 10,"hi" };//10个都是"hi"的元素
//当元素类型没有默认构造函数时必须指定初始值

拷贝容器的一部分进行初始化

//通过指定范围初始化(除array皆可用)
//类型必须可以相互转换
vector<int> vec(ivec.begin(), ivec.end());

拷贝容器进行初始化

//ivec和vec的类型(元素和容器)相同
vector<int> vec(ivec); 
vector<int> vec=ivec;
//array的size必须相同 

列表初始化
当内置类型的初始值存在丢失信息的风险,(例如类型转换时丢失精度),编译器将报错。CP39

//对于array来说数量不够时会进行值初始化
vector<int> vec{ 1,2,3,4,5 };
vector<int> vec={ 1,2,3,4,5 };
//多个初始值只能使用列表初始化
array<int,10> a;

赋值

  • 如果容器大小不同,赋值后为右边容器的大小
  • array的元素类型必须相同
  • 导致左边的迭代器,引用和指针失效
c1=c2;
c={a,b,c};//除array皆可用
assign CP302

swap

  • 类型必须相同
  • 速度更快(除array外只交换容器内部的数据结构,不交换元素)
  • 对于array会交换元素
  • 除array和string不会使迭代器,引用和指针失效(但指向的元素变换了所属的容器)
swap(c1,c2)//尽量使用非成员版
c1.swap(c2)
vector<string> sv1(5);
vector<string> sv2(10);
auto iter=sv1.begin();
/*交换后vec1有10个元素,vec2有5个元素  
  交换的是整个容器内容*/
swap(sv1,sv2);
//交换后iter指向sv2[0]

assign

  • 仅顺序容器使用
  • 类型相容即可
seq.assign(b,e)
seq.assign(i1)
seq.assign(n,t)

大小

c,size()
c.max_size()//可保存的最大元素数目
c.empty()

关系运算符:

  • 除无序关联容器皆可
  • 容器和元素类型必须相同
  • 进行元素的逐对比较
  • 元素的类型必须定义相应的比较运算符

    1. 容器的size和元素都相同才等于
    2. size不同时,size较小时容器的值都等于则小于
    3. 第1次出现相异字符的对比结果

添加

  1. array不可用
  2. 添加的是对象的拷贝,而不是对象本身
  3. 可能导致系统需要重新分配足够的内存并移动
    (对于vector和string的迭代器,指针和引用都会失效)
  4. emplace操作构造(并非拷贝)元素
  5. 对于提供参数必须保证定义了对应的构造函数
//vector和string不支持(需要移动所有元素)
//在头部创建
c.push_front(t);
//先根据参数创建局部临时对象,再放入容器
c.emplace_front(t);
//在容器内部根据参数直接创建对象
//在尾部创建
//forward_list不支持
c.push_back(t);
c.emplace_back(t);
c.insert(iter, p1);
  • 插入到迭代器之前的位置
  • 返回指向新添加的第1个元素的迭代器
list<string> lst;
auto iter=lst.begin();
while(cin>>word)
     iter=lst.insert(iter,word);
  • 可以用其代替push_front,但是根据前面容器的性质可能会很耗时
  • 同时支持插入范围内元素
//指定数量的元素
vec2.insert(iter2, n, t);//迭代器位置之前插入n个t元素                         
//迭代器范围
ivec3.insert(iter3, ivec2.begin(), ivec2.end());
//迭代器的范围不能是同一个容器 
//列表    
ivec4.insert(ivec.begin(), {1,1,1});
  • forward_list有专有版本的insert_after和emplace_after

  • 副作用

    • vector和string:
      如果存储空间并未重新分配,只有插入位置之后的迭代器,指针和引用都会失效。
    • deque:
      插入到首尾位置之外会导致迭代器,指针和引用都会失效。
      在首位置添加只会导致迭代器失效。

访问:

  • 返回引用
  • 有时比begin()/end()更加方便
  • 禁止使用失效的迭代器,指针和引用(添加/删除的副作用)
  • 在循环中添加/删除会注意保持迭代器保持正确的更新
  • 由于尾后迭代器经常失效,必须重新调用end
auto begin=v.begin();
while( begin != v.end() )
{…}
  • 容器为空时函数未定义,使用前必须确保容器非空
c.front()  //返回首元素的引用

forward_list不支持

c.back()   //返回尾元素的引用
  • 只适用于支持随机访问的容器
    程序必须检查保证下标不会越界
c[n]  //n为无符号整数,超出size时函数未定义
//建议使用
c.at(n)  
//n为无符号整数,超出size时抛出out_of_range异常

删除

  • 不适用于array
  • 必须保证被删除的元素是存在的,否则函数未定义
  • -禁止使用失效的迭代器,指针和引用
  • 如果需要则在pop之前保存被抛出的元素
    • 删除尾元素
c.pop_back();   //除forward_list外皆可

删除头元素

c.pop_front();  //除vector和string外皆可
  • forward_list有专有版本的erase_after
    返回被删除元素的下一个元素的迭代器
c.erase(iter)   
//删除迭代器p指向的元素,

当e为尾后迭代器时,返回尾后迭代器

vec.erase(iter1,iter2)   
//删除迭代器(b, e)范围内的元素
  • 删除所有元素
c.clear()
  • 副作用
    • 尾后迭代器总会失效
    • 指向被删除元素的迭代器,指针和引用都会失效。
    • vector和string:
      删除位置之后的迭代器,指针和引用都会失效。
    • deque:
      删除首尾位置之外的元素会导致迭代器,指针和引用都会失效。

改变容器大小

  • array除外
  • 当size大于n时,后面的元素被删除
c.resize(n)
  • 当size小于n时,将新元素添加到后面
c.resize(n)//新元素被默认初始化
c.resize(n,t)//新元素都初始化为t

容器容量管理

  • 只适用于vector和string
    由于vector/string的元素都是连续存储,为了在添加操作时减少重新分配的次数,实现分配时会额外预留一些空间备用。
c.capacity()  //现分配的内存空间可以容纳的元素数量
  1. 当n>c.capacity()时,该函数才会改变容量(≧n);反之函数不做任何改变。
  2. 注意与resize的区别
  3. 尽量不要分配新的空间
c.reserve(n)   //通知容器需要容纳的最小元素数量
  • 只适用于deque、vector和string
    可以向系统请求退回多余的内存空间(不一定执行)
c.shrink_to_fit()  //将capacity()的数量减少为size()

forward_list
由于添加/删除单向链表的元素会改变序列的链接,为了维护,必须访问其前驱以便改变链接。

  • 返回指向首元素之前位置的迭代器(无法解引用)
    对forward_list需要2个迭代器
lst.before_begin()
lst.before_cbegin()
  • 必须保证迭代器不为尾后迭代器
//将t插入到p的后面
lst.insert_after(p,t)
lst.insert_after(p,n,t)
//范围不能在lst内,范围为空返回p
lst.insert_after(p,b,e)
lst.insert_after(p,{…})
//在指定位置后创建新元素,返回指向新元素的迭代器
emplace_after(p,t)
  • 必须保证迭代器不为尾后/指向尾元素的迭代器
//删除p之后的元素
lst.erase_after(p)
//删除从b开始到(不包括)e的元素
lst.erase_after(b,e)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
机器学习是一种人工智能(AI)的子领域,致力于研究如何利用数据和算法让计算机系统具备学习能力,从而能够自动地完成特定任务或者改进自身性能。机器学习的核心思想是让计算机系统通过学习数据中的模式和规律来实现目标,而不需要显式地编程。 机器学习应用非常广泛,包括但不限于以下领域: 图像识别和计算机视觉: 机器学习在图像识别、目标检测、人脸识别、图像分割等方面有着广泛的应用。例如,通过深度学习技术,可以训练神经网络来识别图像中的对象、人脸或者场景,用于智能监控、自动驾驶、医学影像分析等领域。 自然语言处理: 机器学习在自然语言处理领域有着重要的应用,包括文本分类、情感分析、机器翻译、语音识别等。例如,通过深度学习模型,可以训练神经网络来理解和生成自然语言,用于智能客服、智能助手、机器翻译等场景。 推荐系统: 推荐系统利用机器学习算法分析用户的行为和偏好,为用户推荐个性化的产品或服务。例如,电商网站可以利用机器学习算法分析用户的购买历史和浏览行为,向用户推荐感兴趣的商品。 预测和预测分析: 机器学习可以用于预测未来事件的发生概率或者趋势。例如,金融领域可以利用机器学习算法进行股票价格预测、信用评分、欺诈检测等。 医疗诊断和生物信息学: 机器学习在医疗诊断、药物研发、基因组学等领域有着重要的应用。例如,可以利用机器学习算法分析医学影像数据进行疾病诊断,或者利用机器学习算法分析基因数据进行疾病风险预测。 智能交通和物联网: 机器学习可以应用于智能交通系统、智能城市管理和物联网等领域。例如,可以利用机器学习算法分析交通数据优化交通流量,或者利用机器学习算法分析传感器数据监测设备状态。 以上仅是机器学习应用的一部分,随着机器学习技术的不断发展和应用场景的不断拓展,机器学习在各个领域都有着重要的应用价值,并且正在改变我们的生活和工作方式。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值