C++学习记录———容器的简单整理

2023-10-27

1. 容器的概念

容器是用来批量存储数据的集合,数据元素可以是用户自定义类型,也可以是C++预定定义类型。容器类的对象自动申请和释放内存,无需new和delete操作。


容器:顺序容器 和关联容器
顺序容器:元素之间是顺序关系,元素有固定的位置
关联容器:元素之间没有严格物理上的顺序关系。内部是有联系的
顺序容器:Array数组,vector向量,list双向链表,deque
关联容器:map 键值对 ,mulitmap 多重键值对


容器分类如下图所示:

2. 容器的分类

2.1 顺序容器

是一种各个元素直接有顺序关系的线性容器,每个元素都有自己的位置,通过下标或迭代器进行访问,除非删除或者插入的数据改变元素的顺序

本次学习的顺序容器有:array(数组)、string、vector(向量)、list(列表)、deque(队列)

2.1.1 array(数组)

C++11新增的数组,符合容器的设计规范,使用起来更加方便。

关于array的使用

#include <iostream>
#include <array>
using namespace std;

int main()
{
    //创建一个长度为5的int数组
    array<int,5> arr = {1,2,3};
    //取出对应下标的元素值
    cout << arr.at(0) << endl; //1
    cout << arr[1] << endl; //2
    cout << arr[4] << endl; //0

    //更改第四个数据的值为884
    arr[3] = 886;
    cout << arr[3] << endl;

    cout << "-----for------" << endl;
    for(int i = 0; i<arr.size();i++)
    {
        cout << arr.at(i) << " ";
    }
    cout << endl;

    //给所有元素填充一个固定值
    arr.fill(521);


    cout << "-----foreach------" << endl;
    for(int i:arr)
    {
        cout << i << " ";
    }
    cout << endl;

    return 0;
}

2.1.2 string

string是C++源码中自带的类,类可以包含很多成员函数等。

关于string类的函数个人整理后在下面代码中展示:

#include <iostream>

using namespace std;

int main()
{
    //创建一个内容为空的字符串对象
    string s;
    cout << s.empty() << endl; //1

    string s1 = "Monday"; //隐式调用构造函数
    string s2("Monady"); //显示调用构造函数
    cout << (s1==s2) << endl; //0

    string s3(s2); //拷贝构造函数
    s2 = s1; //赋值运算符
    cout << s3 << " " << s2 << endl; //Monady  Monday

    //参数1:char*原字符串 参数2:从前往后保留字符数
    string s4("ASDFF",2);
    cout << s4 << endl; //AS
    //参数1:string原字符串 参数2:从前往后不保留字符数
    string s5(s2,2);
    cout << s5 << endl; //nady

    //参数1:字符数量 参数2:cahr字符内容
    string s6(5,'A');
    cout << s6 << endl; //AAAAA

    //字符串拼接:+
    string s7 = s4 + s6;
    cout << s7 << endl; //ASAAAAA

    //向后追加字符串:append()
    s7.append("YYY").append("WUW");
    cout << s7 << endl; //ASAAAAAYYYWUW

    //向后追加单字符:push_back()
    s7.push_back('p');
    cout << s7 << endl; //ASAAAAAYYYWUWp

    //交换字符串:swap()
    swap(s5,s6);
    cout << s5 << " " << s6 << endl; //AAAAA nday

    //插入字符串:insert() 参数1:插入的位置 参数2:插入的内容
    s7.insert(2,"****");
    cout << s7 << endl; //AS****AAAAAYYYWUWp

    //删除内容:erase() 参数1:删除的起止位置 参数2:删除的字符数
    s7.erase(4,3);
    cout << s7 << endl; //AS**AAAAYYYWUWp

    //替换:replace()  参数1:替换的起始位置 参数2:替换的字符数 参数3:替换的内容
    s7.replace(0,3,"++++");
    cout << s7 << endl;  //++++*AAAAYYYWUWp
    //遍历:使用for即可

    for(int i=0;i<s.size();i++)
    {
        cout<<s[i]<<" ";
    }
    
    cout<<endl;
    //清空:clear()
    s7.clear();
    cout << s7.size() << endl; //0
    return 0;
}

2.1.3 vector

vector内部使用数组实现,最常用的一种顺序容器,适合高效的进行随机存取,不适合插入和删除。可以理解为可变长度的数组,是一种顺序结构的线性表,故他的特性和线性表差不多,如随机访问;且插入删除的时间复杂度是O(n)。

关于vector指针的位置如图所示,我这里设置了一个最大长度为7里面包含5个元素的vector数组,其中first指针指向下标为0的元素,end指针指向最大长度的后一位。

 故last-first即为该表存储的数量,end-first=size即为该表的长度。

当插入的数值超范围后,vector会另外开辟出一块更大的空间用于存储,转移的顺序如下:

1. 转移表内的元素信息

2. 转移first、end、last等指针

3. 删除原有的表,完成转移

由上可知,为确保程序运行的效率,故vector无直接插在首位的函数如:frontpush,后面的list容器可以解决这种问题。

我们现在将我所整理的函数及其功能列出来:

#include <iostream>
#include <vector>

using namespace std;

int main()
{
    //创建一个长度为5向量对象
    vector<int> vec(5);
    cout << vec.size() << endl; //5
    //取出元素值
    cout << vec.at(0) << " " << vec[1] << endl; //0 0
    //向后添加元素
    vec.push_back(12);
    cout << vec.size() << endl; //6 此时长度为6,动态扩充
    //删除最后一个元素
    vec.pop_back();
    //在第二个位置插入元素222
    vec.insert(vec.begin()+1,222);

    //在倒数第二个位置插入元素4
    vec.insert(vec.end()-1,4);

    //删除倒数第一个元素
    vec.erase(vec.end()-1);


    cout << "-----for----" << endl;
    for(int i=0;i<vec.size();i++)
    {
        cout << vec.at(i) << " ";
    }
    cout << endl;

    //清空元素
    vec.clear();
    cout << vec.empty() << endl; //1
    return 0;
}

2.1.4 list

list内部由双向链表实现,元素的内存空间不连续,因此适合高效的进行插入和删除操作,但是不适合使用下标操作(只能通过迭代器指针操作元素),也不适合大量的随机存取。

#include <iostream>
#include <list>

using namespace std;

int main()
{
    //创建一个长度为4的列表对象,每个元素的初始值为“hello”
    list<string> lis(4,"hello");
    cout << lis.empty() << endl; //0
    //向后追加
    lis.push_back("hou");
    //向前追加
    lis.push_front("qian");
    cout << lis.size() << endl; //6

    //在第一个位置插入元素
    lis.insert(lis.begin(),"frist");
    //获取第一个元素
    cout << lis.front() << endl; //frist

    //在最后一个位置插入元素
    lis.insert(lis.end(),"finish");
    //获取最后一个元素
    cout << lis.back() << endl; //finish

    //    删除第一个元素
    lis.pop_front();
    cout << lis.front() << endl; //qian
    //删除最后一个元素
    lis.pop_back();
    cout << lis.back() << endl; //hou

    //第二个位置插入元素
    //注:list的迭代器指针不支持+,可以使用自增或自减
    lis.insert(++lis.begin(),"222");
    //在倒数第二个位置插入元素
    lis.insert(--lis.end(),"lala");

    //在第五个位置插入元素
    //     1、获取起始位置的迭代器指针 只读:const_iterator 可读写:iterator
    list<string>::iterator iter = lis.begin();
    //2、把迭代器指针向后移动4位(参数1:迭代器指针 参数2:向后移动的数量,负数为向前)
    advance(iter,4);
    //3、使用*取内容,即元素本身
    cout << "lis[4]:" << *iter << endl; //hello
    //4、插入元素"555"
    lis.insert(iter,"555");
    cout << "lis[4]:" << *iter << endl; //hello
    //修改第五个元素
    iter = lis.begin();
    advance(iter,4);
    *iter = "exo";
    //删除第四个元素
    iter = lis.begin();
    advance(iter,3);
    lis.erase(iter);

    //排序:按照编码方式
    //    lis.sort();

    //不支持for循环,但是支持foreach
    for(string i:lis)
    {
        cout << i << " ";
    }
    cout << endl;

    //清空
    //    lis.clear();
    //    cout << lis.empty() << endl; //1
    return 0;
}

2.1.5 deque

从API上基本同时兼容vector和list,随机存取和插入删除的性能都介于vector和list直接,算是一种比较均衡 的顺序容器类型。相对而言,deque比较擅长首尾两端的存取操作。因为兼容的缘故deque可以直接使用vector和list二者的函数用法,注意使用时要换函数介绍为deque

2.2 关联容器

各个元素直接没有严格的物理顺序,但是在内部由一个排序特点,因此就可以使用迭代器进行遍历。

常见的关联容器有:map(键值对映射)、multimap(多重键值对映射)等

以map为例,来说明关联容器的使用。

2.2.1 map

map以键值对的方式来存储元素数据,map与multimap的区别仅仅在于一个键对应一个值还是一个键对应多个值,map更为常用。

键作为数据的名称,具有唯一性,而值则不必。

键通过为字符串类型,而值则根据存储的数据类型而定。

#include <iostream>
#include <map>

using namespace std;

int main()
{
    //创建一个元素为空的map对象
    map<string,int> m;
    //插入元素
    m["身高"] = 188;
    m["体重"] = 50;
    m["存款"] = 12000;
    //如果这个键值对已经存在,则表示修改(键名改不了,只能修改值)
    m["存款"] = 15000;
    m.insert(pair<string,int>("年龄",27));
    m.insert(pair<string,int>("工龄",4));

    //在取出数据时应该先进行判断值是否存在,

    if(m.find("存款") != m.end())
    {
        //取出键对应的值 键--first 值--second
        cout << m.find("存款")->second << endl;
    }else
    {
        cout << "存款键不存在" << endl;
    }
    if(m.find("住址") != m.end())
    {
        //取出键对应的值 键--first 值--second
        cout << m.find("住址")->second << endl;
    }else
    {
        cout << "住址键不存在" << endl;
    }

    //删除键值对
    bool result = m.erase("体重");
    cout << m.size() << endl; //4
    if(result)
    {
        cout << "删除体重成功" << endl;
    }else
    {
        cout << "删除体重失败" << endl;
    }
    result = m.erase("收入");
    if(result)
    {
        cout << "删除收入成功" << endl;
    }else
    {
        cout << "删除收入失败" << endl;
    }

    //清空
    m.clear();
    cout << m.empty() << endl; //1
    return 0;
}

2.3 迭代器

C++中为每一个容器类都提供了对应的迭代器类型,用于遍历容器,迭代器是一个特殊的指针。

通常情况下,容器类型可以通过begin或end函数获得头部或尾部的跌大气,随后不断移动迭代器来取出所有的元素。

迭代器遍历的效率是各种方式中最高的。如果只读使用const_iterator,如果读写使用iterator。

#include <iostream>
#include <array>
#include <string>
#include <vector>
#include <list>
#include <deque>
#include <map>

using namespace std;

int main()
{
    string str = "hello";
    for(string::const_iterator iter = str.begin();iter!= str.end();iter++)
    {
        cout << *iter << " ";
    }
    cout << endl;

    array<string,5> arr = {"aaa","bbb","ccc","ddd","eee"};
    for(array<string,5>::const_iterator iter = arr.begin();iter!= arr.end();iter++)
    {
        cout << *iter << " ";
    }
    cout << endl;

    vector<double> vec;
    vec.push_back(11.2);
    vec.push_back(12.2);
    vec.push_back(13.2);
    vec.push_back(14.2);
    vec.push_back(15.2);
    for(vector<double>::const_iterator iter = vec.begin();iter!= vec.end();iter++)
    {
        cout << *iter << " ";
    }
    cout << endl;

    list<string> lis;
    lis.push_back("AA");
    lis.push_back("BB");
    lis.push_back("CC");
    lis.push_back("DD");
    lis.push_back("EE");
    for(list<string>::const_iterator iter = lis.begin();iter!= lis.end();iter++)
    {
        cout << *iter << " ";
    }
    cout << endl;

    deque<int> deq;
    deq.push_back(12);
    deq.push_back(13);
    deq.push_back(14);
    deq.push_back(15);
    deq.push_back(16);
    for(deque<int>::const_iterator iter = deq.begin();iter!= deq.end();iter++)
    {
        cout << *iter << " ";
    }
    cout << endl;

    map<string,string> m;
    m["name"] = "Json";
    m["age"] = "18";
    m["sex"] = "man";
    m["money"] = "10000";
    m["car"] = "benchi";
    for(map<string,string>::const_iterator iter = m.begin();iter != m.end();iter++)
    {
        cout << iter->first << " " << iter->second;
    }
    cout << endl;


    return 0;
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++学习记录———容器的简单整理 的相关文章

  • 使用python批量重命名文件夹中的文件

    目录 一 前言 二 Python重命名文件的方法 三 Python重命名文件夹内的所有图片 四 Python重命名文件夹内的所有图片并按照顺序排序 五 总结 一 前言 在日常工作中 我们经常需要对文件进行重命名 比如将一些图片按照顺序重命名
  • java基础知识-基础语法

    一 变量 a 概念 计算机内存中的一块存储空间 是存储数据的基本单元 b 组成 数据类型 变量名 值 注意 java语言是强类型的编程语言 要求数据类型必须和变量中存储的数据的类型保持一致 c 变量的使用方式 i 声明 语法 数据类型 变量
  • 华为OD机试真题- 最小的调整次数【2023Q1】【JAVA、Python、C++】

    题目描述 有一个特异性的双端队列 该队列可以从头部或尾部添加数据 但是只能从头部移出数据 小A依次执行2n个指令往队列中添加数据和移出数据 其中n个指令是添加数据 可能从头部添加 也可能从尾部添加 依次添加1到n n个指令是移出数据 现在要
  • OpenWrt配置(UCI)

    UCI简介 统一配置接口 Unified Configuration Interface UCI 其目的在于集中OpenWrt系统的配置 基本语法介绍 参考 UCI系统 https wiki openwrt org zh cn doc uc
  • MES系统开发手记(一)

    前言 从ERP开发转到MES系统开发又是将近5年时间了 前后做了几个项目的MES系统 终于想为自己的这几年开发做个总结 写一个比较产品化的MES系统 一 建模 1 基础资料 建立以下几个信息中心 车间资源 产品数据 工艺数据 对制造过程中所

随机推荐

  • gcc编译出现 invalid operands to binary -的解决方法

    在做pcap库抓包的程序中 使用了 pcap head gt caplen unsigned int unsigned char data packet 算式 然后就报 invalid operands to binary 检查代码 其中p
  • 一种为不联网(离线)电脑配置深度学习环境的方法

    1 场景描述 目标电脑为A 无法联网 但是硬件好 需要配置深度学习环境 家用电脑为B 可以联网 硬件条件仅满足日常办公 下面以Tensorflow为例 提供一种环境配置的思路 tensorflow也可以是pytorch等深度学习框架 2 思
  • 程序跑飞原因

    程序跑死原因查找 1 意外中断 是否打开了某个中断 但是没有响应和清除中端标志 导致程序一直进入中断 造成死机假象 2 中断变量处理不妥 若定义某些会在中断中修改的全局变量 这时要注意两个问题 首先为了防止编译器优化中断变量 要在这些变量定
  • docker部署zookeeper集群

    编写启动脚本 docker stop zookeeper docker rm zookeeper docker run restart always privileged true p 2181 2181 name zookeeper ne
  • reset --hard 后如何找回

    问 reset hard 后如何找回 答 拢共分两步 一 找到你想要切回的commit id 二 切过去 一 找到你想要切回的commit id 你的git操作在log中都会有记录 git logs refs heads master 如
  • 惠普ns1005w使用说明_惠普 NS1005w 多功能一体机深度评测:15秒智能闪充 + 全功能手机操控...

    在办公场景中 对打印机的要求比较多 如打印快 成本低 印量大 多功能等 而在桌面型多功能一体机中 HP Laser NS MFP 1005系列 智能闪充加粉式多功能一体机更能满足用户的要求 自从HP Laser NS MFP 1005系列智
  • 华为OD机试 -勾股数(Java)

    题目描述 如果三个正整数A B C A B C 则为勾股数 如果ABC之间两两互质 即A与B A与C B与C均互质没有公约数 则称其为勾股数元组 请求出给定 n m 范围内所有的勾股数元组 输入描述 起始范围 1 lt n lt 10000
  • 【已解决】ImportError: torch.utils.ffi is deprecated. Please use cpp extensions instead.

    本文记录了博主遇到问题 ImportError torch utils ffi is deprecated Please use cpp extensions instead 的解决方案 更新于2019 05 30 背景 博主需要安装一个程
  • ESP32: IDF_PYTHON_ENV_PATH: (not set)

    在Linux下编译esp32工程报错 law law hello world idf py build Setting IDF PATH environment variable home law esp32 esp idf The fol
  • libxxx_intermediates/export_includes’, needed by 解决办法

    xxx intermediates export includes needed by 解决办法 报错信息 ninja error out target product ac8257 demo obj SHARED LIBRARIES li
  • 【深度学习】【U-net】医学图像(血管)分割实验记录

    医学图像分割实验记录 U net介绍 数据集 实验记录 实验1 实验2 fail 实验3 fail 实验4 fail 实验5 fail 实验6 fail 本项目仅用于大创实验 使用pytorch编程 参考价值有限 U net介绍 这里先行挖
  • flutter 本项目做IM消息提醒的思路

    message util 监听接收到消息 container page 在最外层监听消息 如果有收到就弹出弹窗IMNoticeDialog 用converScreen封装过的 可以穿透 可以点击 conversationItem 进入 co
  • 基于MATLAB的战术手势识别功能的设计与实现

    一 课题介绍 手势识别技术是人们生活中常见的一类图像处理技术 也是目前比较火热的研究领域之一 手势识别可以用于人们生活中各种场景 比如利用手势进行电视信息交互 只需要通过手势就能实现对电视机的控制 在很多的VR游戏中 利用手势可以完成各种各
  • mptt介绍

    1 MQTT协议是由IBM开发的即时通讯协议 相比来说比较适合物联网场景的通讯协议 MQTT协议采用发布 订阅模式 所有的物联网终端都通过TCP连接到云端 云端通过主题的方式管理各个设备关注的通讯内容 负责将设备与设备之间消息的转发 2 m
  • 关于Java中对象的比较

    Java对象的比较有这三种 第一种equals 方法是对象值的比较 这是Object类提供的方法 第二种 第三种分别是实现Comparable Comparator接口 Object equals Comparable Comparator
  • 【C++】error LNK2019: 无法解析的外部符号

    转 C error LNK2019 无法解析的外部符号 错误解决方案 今天在实现类模板特例化的时候遇到一个问题 就是把类模板函数实现放到类的cpp文件中 然后在main函数中使用这个类的时候 就会出现无法解析的外部符号 函数名 xxxx 等
  • 深圳求职安全防范手册

    深圳作为中国第四大经济城市 吸引了来自全国各地的大批求职者 因为人口流动性较大 人员组成复杂 治安方面难免会出现一些问题 所以特整理这份求职安全防范手册 希望可以对准备到深圳求职或者已经在深圳求职的你提一个醒 防患于未然 毕竟出门在外 安全
  • 实现一个函数,可以左旋字符串中的k个字符。

    实现一个函数 可以左旋字符串中的k个字符 例如 ABCD左旋一个字符得到BCDA ABCD左旋两个字符得到CDAB 方法一 一 我们先假定这串字符为ABCDE 假设左旋1次 我们可以进行如下操作 ABCDE 一开始 BBCDE 第一次 第一
  • Go语言数据结构-二叉树

    定义 二叉树是一种数据结构 它是由 n n 1 个有限节点组成一个具有层次关系的集合 根节点 最上面的节点 叶子节点 左右子节点都为nil的节点 特点 每个节点有零个或两个子节点 没有父节点的节点称为根节点 每一个非根节点有且只有一个父节点
  • C++学习记录———容器的简单整理

    1 容器的概念 容器是用来批量存储数据的集合 数据元素可以是用户自定义类型 也可以是C 预定定义类型 容器类的对象自动申请和释放内存 无需new和delete操作 容器 顺序容器 和关联容器 顺序容器 元素之间是顺序关系 元素有固定的位置