C++STL之vector容器(万字详解)
文章目录
前言
STL 是“Standard Template Library”的缩写,中文译为“标准模板库”。STL 是 C++ 标准库的一部分,不用单独安装。
C++ 对模板(Template)支持得很好,STL 就是借助模板把常用的数据结构及其算法都实现了一遍,并且做到了数据结构和算法的分离。例如,vector 的底层为顺序表(数组),list 的底层为双向链表,deque 的底层为循环队列,set 的底层为红黑树,hash_set 的底层为哈希表。
vector 常被称为向量容器,因为该容器擅长在尾部插入或删除元素,在常量时间内就可以完成,时间复杂度为O(1);而对于在容器头部或者中部插入或删除元素,则花费时间要长一些(移动元素需要耗费时间),时间复杂度为线性阶O(n)。
一、vector基本概念
使用vector容器时,需要调用头文件#include < vector >
功能
vector数据结构和数组非常相似、也称为单端数组
vector与普通数组区别:
数组是静态空间、而vector可以动态扩展
动态扩展:并不是在原空间之后续接新空间、而是找更大的内存空间、然后将元数据拷贝到新空间、释放原空间
vetcor容器图解
二、vector构造函数
功能描述
创建vector容器
函数原型
vector<T> v; //采用模板实现类实现、默认构造函数
vector(v.begin(), v.end());//将v[begin(),end()]区间中的元素拷贝给本身
vector(n, item)//构造函数将n个item拷贝给本身
vector(const vector &vec);//拷贝构造函数
vector<T> v{a1,a2,a3};//创建的同时指定初始值以及元素个数
代码展示
三、vector赋值操作
功能描述
给vector容器赋值
函数原型
vector& operator=(const vector &vec);//重载等号操作符
assign(begin,end);//将[begin,end]区间中的数据拷贝赋值给本身
assign(n,item);//将n个item拷贝赋值给本身
代码展示
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> v1; //无参构造
for(int i=0;i<10;i++)
v1.push_back(i);
for(vector<int>::iterator it = v1.begin();it != v1.end();it++)
cout<< *it << " ";
cout<<endl;
vector<int> v2(v1.begin(),v1.end());
for(vector<int>::iterator it = v2.begin();it != v2.end();it++)
cout<< *it << " ";
cout<<endl;
vector<int> v3(10,7);
for(vector<int>::iterator it = v3.begin();it != v3.end();it++)
cout<< *it << " ";
cout<<endl;
vector<int> v4(v3);
for(vector<int>::iterator it = v4.begin();it != v4.end();it++)
cout<< *it << " ";
cout<<endl;
vector<int> v5{1,3,4,5,67,8};
for(vector<int>::iterator it = v5.begin();it != v5.end();it++)
cout<< *it << " ";
cout<<endl;
vector<int> v6;
v6 = v1;
for(vector<int>::iterator it = v6.begin();it != v6.end();it++)
cout<< *it << " ";
cout<<endl;
vector<int> v7;
v7.assign(v1.begin(),v1.end());
for(vector<int>::iterator it = v7.begin();it != v7.end();it++)
cout<< *it << " ";
cout<<endl;
vector<int> v8;
v8.assign(10,1);
for(vector<int>::iterator it = v8.begin();it != v8.end();it++)
cout<< *it << " ";
cout<<endl;
return EXIT_SUCCESS;
}
从上到下分别为v1至v8的输出结果
iterator 为C++ STL迭代器,用法详解查看主页博客相关文章
四、vector容量和大小
功能描述
对vector容器的容量和大小操作
函数原型
empty();//判断容器是否为空
capacity();//容器的容量
size();//返回容器中元素的个数
resize(int num);//重新指定容器的长度为num、若容器变长,则以默认值填充新位置。
//若容器变短,则末尾超出容器长度的元素被删除
resize(int num, item);//重新指定容器的长度为num、若容器变长,则以item填充新位置。
//若容器变短,则末尾超出容器长度的元素被删除
判断是否为空 — empty
返回元素个数 — size
返回容器容量 — capacity
重新指定大小 — resize
代码展示
vector<int> v1{1,2,3,4,5,6};
if(v1.empty())
cout<<"v1是空的"<<endl;
else
cout<<"v1不是空的"<<endl;
cout<<v1.empty()<<endl;
cout<<"v1 的容量"<<v1.capacity()<<endl;
cout<<"v1 的元素个数"<<v1.size()<<endl;
v1.resize(10,1);
for(vector<int>::iterator it = v1.begin();it != v1.end();it++)
cout<< *it << " ";
cout<<"v1 的容量"<<v1.capacity()<<endl;
cout<<"v1 的元素个数"<<v1.size()<<endl;
vector自动扩容所以v1的容量从6扩容到了12
五、vector数据存取
功能描述
对vector中的数据的存取操作
函数原型
at(int id);//返回索引id所指的数据
operator[];//返回索引id所指的数据
front();//返回容器中第一个数
back();//返回容器最后一个数据
代码展示
vector<int> v1{1,2,3,4,5,6};
cout<<v1.at(2)<<endl;
cout<<v1[2]<<endl;
cout<<v1.front()<<endl;
cout<<v1.back()<<endl;
六、vector互换容器
功能描述
实现两个容器内元素进行互换
函数原型
swap(v);//将v与本身的元素互换
代码展示
vector<int> v1{1,2,3,4,5,6};
vector<int> v2{7,77,777,7777};
cout<<"v1的元素"<<endl;
for(vector<int>::iterator it = v1.begin();it != v1.end();it++)
cout<< *it << " ";
cout<<endl;
cout<<"v2的元素"<<endl;
for(vector<int>::iterator it = v2.begin();it != v2.end();it++)
cout<< *it << " ";
cout<<endl;
v1.swap(v2);
cout<<"v1的元素"<<endl;
for(vector<int>::iterator it = v1.begin();it != v1.end();it++)
cout<< *it << " ";
cout<<endl;
cout<<"v2的元素"<<endl;
for(vector<int>::iterator it = v2.begin();it != v2.end();it++)
cout<< *it << " ";
cout<<endl;
七、vector预留空间
功能描述
减少vector在动态扩展容量时的扩展次数
函数原型:
reserve(int length);//容器预留length个元素长度,预留位置不初始化,元素不可访问
代码展示
vector<int> v1{1,2,3,4,5,6};
cout<<"v1之前的容量"<<v1.capacity()<<endl;
v1.reserve(10);
cout<<"v1现在的容量"<<v1.capacity()<<endl;
八、vector存放内置数据类型
容器:vector
算法:for_each
迭代器:vector::iterator
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
void Print(int val)
{
cout<<val<<endl;
}
void Vector()
{
//创建容器
vector<int> v;
//存放数据
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
//迭代器遍历
//v.begin() 容器第一个元素
//v.end() 容器最后一个元素
//vector<int>::iterator 获取vector<int>迭代器的类型
vector<int>::iterator v_begin = v.begin();
vector<int>::iterator v_end = v.end();
//第一种遍历方式
while(v_begin != v_end)
{
cout<< *v_begin <<endl;
v_begin++;
}
//第二种遍历方式
for(vector<int>::iterator it = v.begin();it != v.end();it++)
{
cout<< *it << " "<< endl;
}
cout<<endl;
//第三种遍历方式:使用STL提供的标准遍历算法
for_each(v.begin(),v.end(),Print);
}
int main()
{
Vector();
return 0;
}
九、vector存放自定义数据类型
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
//自定义数据类型
class Person {
public:
Person(string name, int age)
{
a_Name = name;
a_Age = age;
}
string a_Name;
int a_Age;
};
//存放对象
void Vector1()
{
//创建容器
vector<Person> v;
Person p1("a",1);
Person p2("b",2);
Person p3("c",3);
Person p4("d",4);
Person p5("e",5);
v.push_back(p1);
v.push_back(p2);
v.push_back(p3);
v.push_back(p4);
v.push_back(p5);
for(vector<Person>::iterator it = v.begin();it != v.end();it++)
{
cout<< "Name: "<<it->a_Name<<" Age:"<<(*it).a_Age<<endl;
}
}
//存放对象指针
void Vector2()
{
//创建容器
vector<Person*> v;
Person p1("a",1);
Person p2("b",2);
Person p3("c",3);
Person p4("d",4);
Person p5("e",5);
v.push_back(&p1);
v.push_back(&p2);
v.push_back(&p3);
v.push_back(&p4);
v.push_back(&p5);
for(vector<Person*>::iterator it = v.begin();it != v.end();it++)
{
Person* p = (*it);
cout<< "Name: "<<p->a_Name<<" Age:"<<(*p).a_Age<<endl;
}
}
int main()
{
Vector1();
Vector2();
return 0;
}
十、vector容器嵌套容器
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
void Vector1()
{
vector<int> v1;
vector<int> v2;
vector<int> v3;
vector<int> v4;
for(int i=0;i< 4;i++)
{
v1.push_back(i + 1);
v2.push_back(i + 2);
v3.push_back(i + 3);
v4.push_back(i + 4);
}
//容器嵌套
vector<vector<int>> v;
//子容器元素插入
v.push_back(v1);
v.push_back(v2);
v.push_back(v3);
v.push_back(v4);
//输出
for(vector<vector<int>>::iterator it = v.begin();it != v.end();it++)
{
for(vector<int>::iterator vit = (*it).begin();vit != (*it).end();vit++)
{
cout<<*vit<<" ";
}
cout<<endl;
}
}
void Vector2()
{
}
int main()
{
Vector1();
Vector2();
return 0;
}
总结
vector 容器是 STL 中最常用的容器之一,它和 array 容器非常类似,都可以看做是对 C++ 普通数组的“升级版”。不同之处在于,array 实现的是静态数组(容量固定的数组),而 vector 实现的是一个动态数组,即可以进行元素的插入和删除,在此过程中,vector 会动态调整所占用的内存空间,整个过程无需人工干预。
另外vector 提供了许多了成员函数供我们使用,详情可参见下表
函数成员 | 函数功能 |
---|---|
begin() | 返回指向容器中第一个元素的迭代器。 |
end() | 返回指向容器最后一个元素所在位置后一个位置的迭代器,通常和 begin() 结合使用。 |
rbegin() | 返回指向最后一个元素的迭代器。 |
rend() | 返回指向第一个元素所在位置前一个位置的迭代器。 |
cbegin() | 和 begin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。 |
cend() | 和 end() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。 |
crbegin() | 和 rbegin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。 |
crend() | 和 rend() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。 |
size() | 返回实际元素个数。 |
max_size() | 返回元素个数的最大值。这通常是一个很大的值,一般是 232-1,所以我们很少会用到这个函数。 |
resize() | 改变实际元素的个数。 |
capacity() | 返回当前容量。 |
empty() | 判断容器中是否有元素,若无元素,则返回 true;反之,返回 false。 |
reserve() | 增加容器的容量。 |
shrink _to_fit() | 将内存减少到等于当前元素实际所使用的大小。 |
operator[ ] | 重载了 [ ] 运算符,可以向访问数组中元素那样,通过下标即可访问甚至修改 vector 容器中的元素。 |
at() | 使用经过边界检查的索引访问元素。 |
front() | 返回第一个元素的引用。 |
back() | 返回最后一个元素的引用。 |
data() | 返回指向容器中第一个元素的指针。 |
assign() | 用新元素替换原有内容。 |
push_back() | 在序列的尾部添加一个元素。 |
pop_back() | 移出序列尾部的元素。 |
insert() | 在指定的位置插入一个或多个元素。 |
erase() | 移出一个元素或一段元素。 |
clear() | 移出所有的元素,容器大小变为 0。 |
swap() | 交换两个容器的所有元素。 |
emplace() | 在指定的位置直接生成一个元素。 |
emplace_back() | 在序列尾部生成一个元素。 |
除此之外,C++ 11 标准库还新增加了 begin() 和 end() 这 2 个函数,和 vector 容器包含的 begin() 和 end() 成员函数不同,标准库提供的这 2 个函数的操作对象,既可以是容器,还可以是普通数组。当操作对象是容器时,它和容器包含的 begin() 和 end() 成员函数的功能完全相同;如果操作对象是普通数组,则 begin() 函数返回的是指向数组第一个元素的指针,同样 end() 返回指向数组中最后一个元素之后一个位置的指针(注意不是最后一个元素)。