STL——vector容器

  • vector对象的概念
  • vector基本操作
  • vector对象的初始化、赋值
  • vector查找、替换(已在上一片 string类 博客总结过了,不再总结)
  • vector添加、弹出元素(头部、尾部)
  • vector容器的遍历(通过数组的方式、通过迭代器)
  • vector删除、插入操作(指定元素删除/插入、区间删除/插入、一次插入多个相同的元素)
  • 迭代器介绍(输入迭代器、输出迭代器、正向迭代器、双向迭代器)
  • vector举例应用

在这片文章中我参考了许多人的博客,甚至有一些部分是直接copy的,最终做了一个详细的vector用法总结

vector用法参考


vectot容器的简介

  1. vector 是一个将元素置于动态数组中加以管理的容器。
  2. vector 支持随机存取元素(支持索引值直接存取,用[]操作符或 at()方法,来下标来访问)
  3. vecotr 在尾部添加和移除元素非常快,但是在中间和头部添加和移除却很费事。
  4. vector存储数据时,会分配一个存储空间,如果继续存储,该分配的空间已满,就会分配一块更大的内存,把原来的数据复制过来,继续存储,这些性能也会一定程度上会有损耗

vector基本操作

(1). 容量
向量大小: vec.size();
向量最大容量: vec.max_size();
更改向量大小: vec.resize();
向量真实大小: vec.capacity();
向量判空: vec.empty();
减少向量大小到满足元素所占存储空间的大小: vec.shrink_to_fit(); //shrink_to_fit
(2). 修改 多个元素赋值: vec.assign(); //类似于初始化时用数组进行赋值
末尾添加元素: vec.push_back();
末尾删除元素: vec.pop_back();
任意位置插入元素: vec.insert();
任意位置删除元素: vec.erase();
交换两个向量的元素: vec.swap();
清空向量元素: vec.clear();

vector类的对象的构造

    //vector 采用模版类来实现 vector<T> vec;
vector<int> v1 //从模版实例化出存放int类型元素的 v1 容器
vector<double> v2 //从模版实例化出存放double类型元素的 v1 容器 //vector 尖括号内可以实例化出 指针类(包括自定义的数据类型的指针)型和自定义的 数据类型的 容器
vector<int *> v3// 定义存放 int型变量的地址的容器
class A {}; // 自几定义数据类型 A
vector<A> v4; //定义存放A类型数据的容器
vector<A *> v5;//定义存放 A类型变量的地址的容器 //⚠️注意:由于容器元素的初始化/赋值是按值传递复制的进行的,所以此时 A类 必须提供拷贝构造函数,以保证 A类的对象之间拷贝正常

初始化

    v1.push_back(1); //向v1中添加一个 1
v1.push_back(2); //向v2中添加一个 2
v1.push_back(3); //向v3中添加一个 3
int ar[3] = {1,3,5};
vector<int> vec={1,3,5}; //用列表初始化
vector<int>v2 = v1; //用vector的拷贝构造函数
vector<int>v3(v1);
vector<int>v4(v1.begin(),v1.end());//区间初始化
vector<int>v5(ar,ar+3); //用数组区间初始化
vector<int>v6(5,0); //用五个0进行初始化

赋值


    //vector赋值
//第一类赋值法
v4.assign(10,0); //给v4赋上10个零
v3.assign(ar,ar+2);
v2.assign(v1.begin(),v1.end());
//第二类赋值法(⚠️运用下标法 [] 必须先给vector容器申请空间,以供下标访问否则出错,如果此时用push_back()将把元素插入到先前申请的空间之后)
vector<int> v5(10); //提前申请存储10元素的空间,此时10个元素的值均为0
for(int i=0;i<10;i++)
v5[i]=i+1;
//第三类赋值法,通过迭代器的方式去赋值
for(vector<int>::iterator it =v5.begin();it<v5.end();it++)
*it = 0;

添加、弹出元素(头部、尾部)

    vector<int> v1;
//vector 的增添、弹出、删除元素
//添加
v1.push_back(1); //向v1中添加一个 1
v1.push_back(2); //向v2中添加一个 2
v1.push_back(3); //向v3中添加一个 3
print(v1);
//弹出
v1.pop_back(); //弹出尾部的一个元素
print(v1);
//尾元素的访问与修改
cout<<v1.back(); //通过back()函数去访问v1的尾元素
cout<<v1.front();//通过front()函数去访问v1的首元素
v1.back() = 10; //由于back()函数返回值为引用,所以可以通过back(),来改变尾元素的值
v1.front() = 20; // 与⬆️同理

遍历

    vector<int> v1={1,3,5};
//vector的遍历
//1.用for循环
for(int i=0;i<3;i++)
cout<<v1[i];
//2.用基于范围的for循环
for(int &i:v1)
{
cout<<i;
i = 10; //有 i 被声明的时候是以引用的方式,所以可以通过 i 来改变v1中元素的值
}
//3.用迭代器
for(vector<int>::iterator it = v1.begin();it<v1.end();it++)
{
cout<<*it;
* it = 10; //通过it指针去改变v1的值
}

删除,插入操作

    int ar[3] = { 1, 3, 5};
vector<int> v1={1,2,3};
vector<int> vec={1,3,5};
//删除操作
注意⚠️:用erase()删除完后元素后,它的返回值是一个指向下一个元素(挨着最后一个被删除的元素的元素)的迭代器
vec.erase(vec.begin(),vec.end()); //删除[vec.begin(),vec.end())区间的元素
vec.erase(vec.begin()); //删除vec.begin()这个位置的元素
//插入
vec.insert(vec.begin(), 0); //在vec.begin() 位置之前 插入元素
vec.insert(vec.end(), v1.begin(),v1.end()); //在vec.end() 之前插入在[v1.begin(),v1.end())区间内的元素
vec.insert(vec.begin(),10,0); //在vec.begin()之前插入10个0元素
vec.insert(vec.begin(),ar,ar+3);![ebd4c8678baf58da184575ee8ca5b528.png](evernotecid://2C354EAE-828A-4D61-888B-9453DC360564/appyinxiangcom/25418762/ENResource/p334)

迭代器


迭代器的介绍:

  • 迭代器类似于指针类型,它只想一个特定的位置,它也提供了对对象的间接访问
  • 指针是C语言中就有的东西,而迭代器是C++中才有的
  • 使用迭代器:和指针不一样的是,获取迭代器不是使用取地址符,有迭代器的类型同时拥有返回迭代器的成员,比如,容器都有的成员begin和end,其中begin成员负责返回指向容器第一个元素的迭代器,如:auto b = v.begin();end成员则负责返回指向容器的尾元素的下一个位置的迭代器,也就是说指向的是容器的一个本不存在的尾部。如果容器为空,则begin和end返回的是同一个迭代器,都是尾后迭代器。
  • 迭代器提供一个对容器对象或者string对象访问的方法,并且定义了容器范围

输入、输出迭代器

  • 输入迭代器:又叫“只读迭代器“,它只能从容器中读取元素,一次读出一个迭代器向前移,同一个输入迭代器不能遍历两次容器
  • 输出迭代器:又叫“只写迭代器”,它只能从容器总写入元素,一次写入一个迭代器向前移,同一个输出迭代器不能遍历两次容器

正向迭代器、双向迭代器

  • 正向迭代器:所谓正向迭代器指的是只能正向走,而不能反向走,一个在一个指着(停留在)一个元素多次,而且一次移动多个位置,可以通过 ++ += (不可以通过 – -= 运算符)
  • 双向迭代器:所谓正向迭代器指的是可以可以正反两个方向走,支持随机访问容器,一次移动多个位置,可以通过 ++ – += -= 运算符来完成

迭代器理解

  • 迭代器的类型:
  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xP89GMwr-1574571844427)(evernotecid://2C354EAE-828A-4D61-888B-9453DC360564/appyinxiangcom/25418762/ENResource/p332)]
  • 1vector::iterator it;//it可以读写vector的元素
  • 2string::iterator it2;//it2可以读写string对象中的字符
  • 3vector::const_iterator it3;//it3只能读元素,不能写元素
  • 4string::const_iterator it4;//it4只能读字符,不能写字符

  • 迭代器的区别

    const_iterator和常量指针差不多,能读取但不能修改它所指的元素值,而iterator可读可写。如果容器或string对象是一个常量,只能使用const_iterator,如果不是常量,那么既能使用iterator又能使用const_iterator。

    如果容器或对象只需读操作而无需写操作的话最好使用常量类型(const_iterator),为了便于获取常量迭代器,C++11新引入了两个新函数,分别是cbegin和cend,类似于begin和end,不同之乎在于只能返回const_iterator.

    注意:但凡是使用了迭代器的循环体,都不要向迭代器所属的容器添加元素

  • 迭代器运算

1iter + n 迭代器加上一个数值仍得一个迭代器,所指位置向前移动n个元素

2iter - n 迭代器减去一个数值仍得一个迭代器,所指位置向后移动n个元素

3iter += n 等价于iter + n

4iter -= n 等价于iter - n

5iter1 - iter2 两个迭代器相减的结果是他们之间距离,其类型是名为difference_type的带符号整数

6 >、>=、<、<= 位置离begin近的元素较小


迭代器的应用

    //迭代器的应用
//1. 迭代器的声明
vector<int> v1{1,3,5};
vector<int>::iterator it1 = v1.begin(); //声明一个双向迭代器,(begin())并赋值为v1元素的首地址
vector<int>::const_iterator it2 = v1.cbegin(); //只能读容器的值,而不能改变容器的值,cbegin(),是一个指向容器首元素的地址常量,cend()同理如此
vector<int>::reverse_iterator it3 = v1.rbegin(); //声明一个反向迭代器,(rbegin()指向最后一个元素,rend()指向容器第一个元素位置之前)
for( ;it2 < v1.cend();it2++)
{
cout<<*it2;
//*it2 = 10; 这一条错误 因为 it2 是常量迭代器
}
for( ;it3 < v1.rend();it3++)
{
cout<<*it3<<endl; //输出结果:3 2 1
*it3 = 10; //通过指针去赋值
cout<<*it3<<endl;
}
  • 对rbegin()和rend()的理解

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h1dfhtf2-1574571844431)(evernotecid://2C354EAE-828A-4D61-888B-9453DC360564/appyinxiangcom/25418762/ENResource/p334)]

vector与迭代器 举例应用

//关于STL中vector容器的学习,编译运行后边看代码,边看执行结果效果更佳,不过看别人的代码一百遍,不如自己动手写一遍
#include <vector>//头文件
#include <iostream>
#include <algorithm>
using namespace std; void print(vector <int> v);
bool mycmpare(const int &a, const int &b){
return a>b;
}
int main ()
{
//创建vector对象三种常用的方式,此处存储元素类型是int,还可以是double、char、long long等基本数据类型,甚至是string基本字符序列容器
vector <int> v1;//不指定容器的元素个数的定义一个用来存储整型的向量容器
cout<<"v1:"<<endl;
print(v1);
/*运行结果
v1:
大小为:0
*/ vector <int> v2(5);//指定容器的元素个数的定义一个大小为10的用来存储整型的向量容器,默认初始化为0
cout<<"v2:"<<endl;
print(v2);
/*运行结果
v2:
大小为:5
0 0 0 0 0
*/ vector <int> v3(5,1);//也可指定初始值,此处指定为1
cout<<"v3:"<<endl;
print(v3);
/*运行结果
v3:
大小为:5
1 1 1 1 1
*/ //另外事先指定不指定大小都无所谓,指定了大小也可以随时使用push_back()对vector容器进行尾部扩张
v1.push_back(1);//向空的vector容器尾部扩张,追加元素为1
cout<<"v1:"<<endl;
print(v1);
v3.push_back(2);//向已有元素的vector容器尾部扩张,追加元素为2
cout<<"v3:"<<endl;
print(v3);
/*运行结果
v1:
大小为:1
1 v3:
大小为:6
1 1 1 1 1 2
*/ //插入元素使用insert()方法,要求插入的位置是迭代器的位置,而不是元素的下标
v3.insert(v3.begin(),3);//在最前面插入3
cout<<"v3:"<<endl;
print(v3); v3.insert(v3.end(),3);//在末尾追加3,此处等同于push_back()
cout<<"v3:"<<endl;
print(v3);
/*运行结果
v3:
大小为:7
3 1 1 1 1 1 2 v3:
大小为:8
3 1 1 1 1 1 2 3
*/ int i;
for(i=0;i < v3.size();i++){//只可赋值到已扩张位置
v3[i]=i;
}
//要删除一个元素或者一个区间中的所有元素时使用erase()方法
v3.erase(v3.begin()+2);//删除第2个元素,从0开始计数
cout<<"v3:"<<endl;
print(v3);
/*运行结果
v3:
大小为:7
0 1 3 4 5 6 7
*/
v3.erase(v3.begin()+1,v3.begin()+3);//删除第1个到第3个元素区间的所有元素
cout<<"v3:"<<endl;
print(v3);
/*运行结果
v3:
大小为:5
0 4 5 6 7
*/
//由结果可知,erase()方法同insert()方法一样,操作的位置都只是迭代器的位置,而不是元素的下标 //要想清空vector(),使用clear()方法一次性删除vector中的所有元素
cout<<"v2:"<<endl;
print(v2);
/*运行结果
v2:
大小为:5
0 0 0 0 0
*/
v2.clear();
if(v2.empty()) cout<<"v2经过使用clear()方法后为空\n";
print(v2);
/*运行结果
v2经过使用clear()方法后为空
大小为:0
*/ //要想将向量中某段迭代器区间元素反向排列,则使用reverse()反向排列算法,需要添加algorithm头文件
cout<<"v3反向排列前:"<<endl;
print(v3);
reverse(v3.begin(),v3.end());//全部反向排列
cout<<"v3反向排列后:"<<endl;
print(v3);
/*运行结果
v3反向排列前:
大小为:5
0 4 5 6 7 v3反向排列后:
大小为:5
7 6 5 4 0
*/ //要想将向量中某段迭代器区间元素进行排序,则使用sort()算法
cout<<"v3升序排列前:"<<endl;
print(v3);
sort(v3.begin(),v3.end());//默认升序排列
cout<<"v3升序排列后:"<<endl;
print(v3);
/*运行结果
v3升序排列前:
大小为:5
7 6 5 4 0 v3升序排列后:
大小为:5
0 4 5 6 7
*/ //自定义排序比较函数,此处降序
cout<<"v3降序排列前:"<<endl;
print(v3);
sort(v3.begin(),v3.end(),mycmpare);
cout<<"v3降序排列后:"<<endl;
print(v3);
/*运行结果
v3降序排列前:
大小为:5
0 4 5 6 7 v3降序排列后:
大小为:5
7 6 5 4 0
*/
} void print(vector <int> v)
{
//cout<<"下标方式访问:"<<endl;
cout<<"大小为:"<<v.size()<<endl;
int i;
for(i=0;i< v.size();i++){
cout<<v[i]<<' ';
}
cout<<endl<<endl; /*cout<<"用迭代器访问:"<<endl;
//定义迭代器变量it,类型与容器元素类型保持一致
vector<int>::iterator it;
for(it=v.begin(); it != v.end(); it++){
cout<<*it<<' ';
}
cout<<endl<<endl;*/
}

C++STL(二)——vector容器的更多相关文章

  1. 带你深入理解STL之Vector容器

    C++内置了数组的类型,在使用数组的时候,必须指定数组的长度,一旦配置了就不能改变了,通常我们的做法是:尽量配置一个大的空间,以免不够用,这样做的缺点是比较浪费空间,预估空间不当会引起很多不便. ST ...

  2. 跟我一起学STL(2)——vector容器详解

    一.引言 在上一个专题中,我们介绍了STL中的六大组件,其中容器组件是大多数人经常使用的,因为STL容器是把运用最广的数据结构实现出来,所以我们写应用程序时运用的比较多.然而容器又可以序列式容器和关联 ...

  3. 【C++】STL,vector容器操作

    C++内置的数组支持容器的机制,但是它不支持容器抽象的语义.要解决此问题我们自己实现这样的类.在标准C++中,用容器向量(vector)实现.容器向量也是一个类模板.标准库vector类型使用需要的头 ...

  4. STL中vector容器实现反转(reverse)

    vector容器中实现可以通过以下两种方式实现: #include "stdafx.h" #include <vector> #include <iostream ...

  5. STL 查找vector容器中的指定对象:find()与find_if()算法

    1 从vector容器中查找指定对象:find()算法 STL的通用算法find()和find_if()可以查找指定对象,参数1,即首iterator指着开始的位置,参数2,即次iterator指着停 ...

  6. STL:vector容器用法详解

    vector类称作向量类,它实现了动态数组,用于元素数量变化的对象数组.像数组一样,vector类也用从0开始的下标表示元素的位置:但和数组不同的是,当vector对象创建后,数组的元素个数会随着ve ...

  7. STL之vector容器详解

    vector 容器 vector是C++标准模版库(STL,Standard Template Library)中的部分内容.之所以认为是一个容器,是因为它能够像容器一样存放各种类型的对象,简单的说: ...

  8. (转载)C++STL中vector容器的用法

     vector是C++标准模板库中的部分内容,它是一个多功能的,能够操作多种数据结构和算法的模板类和函数库.vector之所以被认为是一个容器,是因为它能够像容器一样存放各种类型的对象,简单地说vec ...

  9. STL笔记(に)--vector容器

    Vector 1.可变长的动态数组 2.需包含头文件#include<vector> (当然,如果用了万能头文件#include<bits/stdc++.h>则可忽略) 3.支 ...

  10. [转]STL之vector容器详解

    vector 容器 vector是C++标准模版库(STL,Standard Template Library)中的部分内容.之所以认为是一个容器,是因为它能够像容器一样存放各种类型的对象,简单的说: ...

随机推荐

  1. 关于使用Binlog和canal来对MySQL的数据写入进行监控

    先说下Binlog和canal是什么吧. 1.Binlog是mysql数据库的操作日志,当有发生增删改查操作时,就会在data目录下生成一个log文件,形如mysql-bin.000001,mysql ...

  2. CVPR 2020 三篇有趣的论文解读

    作者 | 文永亮 学校 | 哈尔滨工业大学(深圳) 研究方向 | 视频预测.时空序列预测 目录 AdderNet - 其实不需要这么多乘法 Deep Snake for Real-Time Insta ...

  3. 【Java实用工具】——使用oshi获取主机信息

    最近在筹划做一个监控系统.其中就要获取主机信息,其中遇到一些问题.在此做个记录,以便以后查阅. 在该监控系统中,想要做到主机的CPU.内存.磁盘.网络.线程.JVM内存.JVM GC 等维度的监控,J ...

  4. 如何使用Kibana

    目录 前言 一.安装 二.加载自定义索引 三.如何搜索数据 四.如何切换中文 五.如何使用控制台 六.可视化图表 七.使用仪表盘 前言 Kibana 是为 Elasticsearch设计的开源分析和可 ...

  5. 在Windows中像Linux里一样使用CMake和make

    1. 安装GCC环境 1.1 安装MinGW(Minimalist GNU for Windows) 首先下载MinGW,并安装.安装完成之后运行MinGW Installer.界面如下.勾选自己需要 ...

  6. IntelliJ IDEA 常用快捷键(转载)

    转自:http://www.open-open.com/lib/view/open1396578860887.html Ctrl+Shift + Enter,语句完成“!”,否定完成,输入表达式时按 ...

  7. How to do error checking in CUDA(如何在CUDA里做错误检查)

    https://codeyarns.com/2011/03/02/how-to-do-error-checking-in-cuda/ Error checks in CUDA code can hel ...

  8. CSS每日学习笔记(0)

    7.29.2019 1. CSS 指层叠样式表 (Cascading Style Sheets) 样式定义如何显示 HTML 元素 样式通常存储在样式表中 把样式添加到 HTML 4.0 中,是为了解 ...

  9. Docker学习-私有仓库docker-registry的使用

    1.从docker官方仓库下载registry 2.将registry放进容器内 3.在官方下载镜像上传本地仓库 4.私有仓库docker-registry使用的常见问题 5.配置阿里云镜像加速器 假 ...

  10. HBU-数据库第五周作业

    第五周数据库作业 注意 MySQL的数据库名.表名.列名.别名大小写规则是这样的: 1.数据库名与表名是严格区分大小写的: 2.表的别名是严格区分大小写的: 3.列名与列的别名在所有的情况下均是忽略大 ...