目录
3.3.vector中的元素排序(这里只是简单介绍一些对stl的算法,详细了解可以查看algorithm)
3.4.ve.size(),ve.capacity(),ve.resize(),ve.reserve()
1.定义
向量(vector)是一个封装了动态数组的顺序容器,它可以存放各种类型的对象是c++中一个较为常见且比较重要的容器,在C++下使用vector我们需要引入#include<vector>头文件
2.基本函数
2.1.vector 构造:
- std::vector<int> ve:创建一个空的vector
- std::vector<int> ve {1,2,3}:创建一个有元素1,2,3的vector
- std::vector<int> ve(20):创建一个有20个元素0的vector
- std::vector<int> ve(20,2):创建一个有20个元素2的vector
- std::vector<int> ve1(ve):创建一个和ve相同的vector
- std::vector<int> ve2(ve1.begin(),ve1.end()):创建一个有[ve.begin(),ve.end()]之间元素的vector
2.2.vector添加元素
- 如果vector中所对下标已申请空间,我们可以直接赋值(当vector.capacity()包含该下标,我们就可以直接访问):ve[1]=2
- 如果我们需要扩展vector的空间可以使用以下函数
- ve.push_back(x):在向量尾部添加一个元素x
- ve.insert(ve.begin()+1, 3, 4):在ve[1]前加3个元素‘4’
- ve.insert(ve.begin() + 1, ve.begin(), ve.end()):在ve[1]前按顺序加ve的所有元素
- ve.insert(ve.begin() + 1, {1,2,3}):在ve[1]前按顺序加入{1,2,3}
2.3.vector删除元素
- ve.pop_back():删除ve中最后一个元素
- ve.erase(ve.begin() + 1):删除ve[1]
- ve.clear():删除ve所有元素
2.4.vector重要的迭代器
- ve.begin():返回正向迭代器的第一个元素
- ve.end():返回正向迭代器的最后一个元素的下一个位置
- ve.rbegin():返回反向迭代器的第一个元素,即vector中的最后一个元素
- ve.rend():返回反向迭代器的最后一个元素的下一个位置,即vector中的第一个元素的前一个位置
- ve.front():返回vector开头一个元素的引用
- ve.back():返回vector最末一个元素的引用
2.5.vector其他函数
- ve.empty():判断ve是否为空
- ve.size():返回当前向量中元素个数
- ve.capacity():返回当前向量中申所能容纳的元素个数,乘以类型大小为该向量申请的空间大小
3.vector使用实例
3.1.初始化vector中的元素
- 上面已经介绍了多种如何声明一个vector,如何在vector中插入一个新的元素,下面介绍使用itoa对vector中的元素初始化
#include <numeric>
#include<iostream>
#include<vector>
void main()
{
std::vector<int> ve;
ve.resize(10);
std::iota(ve.begin(), ve.end(), 1);
for (auto ll: ve)
{
std::cout << ll << std::endl;
}
}
3.2.遍历vector中的元素
- 我们可以直接使用下表遍历vector中的元素
#include<vector>
#include<iostream>
int main()
{
std::vector<int> a(5);
a[0]=3;
a[1]=4;
a[2]=5;
a[3]=6;
a[4]=7;
for(int i=0;i<a.size();i++)
{std::cout<<a[i]<<std::endl;}
return 0;
}
- 我们可以借助ve.begin(),ve.end()访问vector中的元素
#include<vector>
#include<iostream>
int main()
{
std::vector<int> a(5);
a[0]=3;
a[1]=4;
a[2]=5;
a[3]=6;
a[4]=7;
for(auto i=a.begin();i!=a.end();i++)
{std::cout<<*i<<std::endl;}
return 0;
}
- 还有一种方式可以遍历vector的元素
#include<vector>
#include<iostream>
int main()
{
std::vector<int> a(5);
a[0]=3;
a[1]=4;
a[2]=5;
a[3]=6;
a[4]=7;
for(auto i:a)
{std::cout<<i<<std::endl;}
return 0;
}
- 我们还可以使用for_each对vector中的元素进行遍历
#include<vector>
#include<algorithm>
#include<iostream>
void out(int x)
{
std::cout << x << std::endl;
}
void main()
{
std::vector<int> a(5);
a[0] = 3;
a[1] = 4;
a[2] = 5;
a[3] = 6;
a[4] = 7;
std::for_each(std::begin(a), std::end(a), out);
}
3.3.vector中的元素排序(这里只是简单介绍一些对stl的算法,详细了解可以查看algorithm)
- 我们可以直接使用algorithm中的函数完成对vector中元素的排序(sort完成正序排序,reverse完成反向排序)
#include<iostream>
#include<algorithm>
#include<vector>
void main()
{
std::vector<int> ve;
ve.push_back(12);
ve.push_back(6);
ve.push_back(11);
ve.push_back(7);
ve.push_back(13);
std::sort(ve.begin(),ve.end());
for (auto ll : ve)
{
std::cout << ll << std::endl;
}
std::reverse(ve.begin(), ve.end());
for (auto ll : ve)
{
std::cout << ll << std::endl;
}
}
- 但vector中元素类型并不总是基础类型,当vector中元素不是基础类型的时候,我们可能要按照我们的需求重载sort和reverse
#include<iostream>
#include<algorithm>
#include<vector>
#include<string>
struct Unit
{
std::string a;
int size ;
};
bool compare(Unit a,Unit b)
{
return a.size < b.size;
}
void main()
{
std::vector<Unit> ve;
ve.push_back({ "aaa", 3 });
ve.push_back({ "aaaaaaa", 7 });
ve.push_back({ "aa", 2 });
ve.push_back({ "aaaaaa", 6 });
ve.push_back({ "aaaa", 4 });
std::sort(ve.begin(), ve.end(), compare);
for (auto ll : ve)
{
std::cout << ll.a<<" "<<ll.size << std::endl;
}
}
- 我们还可以使用重载运算符的方式按照我们的需求重载sort和reverse
#include<iostream>
#include<algorithm>
#include<vector>
#include<string>
struct Unit
{
std::string a;
int size ;
};
bool operator<(const Unit x, const Unit y)
{
return x.size < y.size;
}
void main()
{
std::vector<Unit> ve;
ve.push_back({ "aaa", 3 });
ve.push_back({ "aaaaaaa", 7 });
ve.push_back({ "aa", 2 });
ve.push_back({ "aaaaaa", 6 });
ve.push_back({ "aaaa", 4 });
std::sort(ve.begin(), ve.end());
for (auto ll : ve)
{
std::cout << ll.a<<" "<<ll.size << std::endl;
}
}
- 我们也可以使用max_element和min_element查找vector中最大值,最小值的函数
#include<iostream>
#include<algorithm>
#include<vector>
void main()
{
std::vector<int> ve1;
ve1.push_back(1);
ve1.push_back(2);
ve1.push_back(3);
ve1.push_back(4);
ve1.push_back(5);
auto max_count = std::max_element(std::begin(ve1), std::end(ve1));
std::cout << *max_count << std::endl;
}
- 同样我们也可以对max_element和min_element查找vector进行重载
#include<iostream>
#include<algorithm>
#include<vector>
#include<string>
struct Unit
{
std::string a;
int size ;
};
bool compare(Unit a,Unit b)
{
return a.size < b.size;
}
void main()
{
std::vector<Unit> ve;
ve.push_back({ "aaa", 3 });
ve.push_back({ "aaaaaaa", 7 });
ve.push_back({ "aa", 2 });
ve.push_back({ "aaaaaa", 6 });
ve.push_back({ "aaaa", 4 });
std::sort(ve.begin(), ve.end(), compare);
auto max_count = std::max_element(std::begin(ve), std::end(ve), [](Unit pr1, Unit pr2){ return pr1.size < pr2.size; });
std::cout << max_count->a<<" "<<max_count->size<< std::endl;
}
3.4.使用shuffle对vector中的元素随机排序
- 我们可以使用shuffle对vector中的元素随机排序,可以参见下面一个例子
#include<iostream>
#include<vector>
#include<algorithm>
#include <random>
#include <chrono>
void main()
{
std::vector<int> a;
srand(time(NULL));
a.push_back(11);
a.push_back(14);
a.push_back(19);
a.push_back(13);
a.push_back(17);
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
std::shuffle(a.begin(), a.end(), std::default_random_engine(seed));
for (auto ll : a)
{
std::cout << ll << " ";
}
}
3.5.ve.size(),ve.capacity(),ve.resize(),ve.reserve()
根据上面的介绍ve.size()是当前向量中元素个数,而ve.capacity()实际上和该向量申请空间相关,所以ve.size()<=ve.capacity()。但在一个vector应该可以被访问到的是ve.size()中的元素,而在ve.size()和ve.capacity()之间的是未初始化的元素,这些元素是不可以被访问到的。在visual studio2013中ve.size()和ve.capacity()之间的元素不可以访问,而在linux下,使用g++或clang++变异,我们会发现ve.size()和ve.capacity()之间的元素会被初始化为一个常数,大家可以在不同变异环境下运行下面的程序验证这件事
#include<stdio.h>
#include<vector>
#include<iostream>
int main()
{
std::vector<int> a(10);
a.push_back(6);
a.push_back(2);
a.push_back(3);
std::cout<<a.capacity()<<std::endl;
std::cout<<a.size()<<std::endl;
std::cout<<a[11]<<std::endl;
for(int i=0;i<20;i++)
{std::cout<<a[i]<<std::endl;}
return 0;
}
那么ve.resize(),ve.reserve()和ve.size(),ve.capacity()有什么关系,因为ve.resize()可以更改ve.size()的值,ve.reserve()可以更改ve.capacity()的值。当ve.resize()>ve.capacity()的时候,vector将调用realloc申请新的空间(在visual studio2013下在原空间基础上再申请大小的空间,在linux下在原空间基础上再申请ve.size()大小的空间,为什么要申请大于我们当时需要的re.size()的空间,是因为每一次申请新空间都要花费较多的时间),但是在linux中vector在调用realloc申请新空间的时候并没有将原空间的内容清除,所以在原先的空间中我们依旧可以找到vector的内容,我们可以运行下面的程序调试观察:
#include<vector>
#include<iostream>
int main()
{
std::vector<int> a(10);
a[8]=6;
a[9]=7;
long long s=(long)&a[8];
long long s1=(long)&a[0];
std::cout<<&a[8]<<std::endl;
std::cout<<s<<std::endl;
a.resize(100);
int *aa=(int *)s;
std::cout<<*aa<<std::endl;
a[99]=2;
a[98]=4;
return 0;
}
还要注意clear()只是将vector.size设为0,但是vector申请的空间并没有释放,而且一些vector的元素还是可以访问到的,下面例子将说明这个问题。
#include<vector>
#include<iostream>
int main()
{
std::vector<int> a(10);
a[8]=6;
a[9]=7;
a.clear();
std::cout<<a.size()<<std::endl;
std::cout<<a.capacity()<<std::endl;
std::cout<<a[8]<<std::endl;
return 0;
}
(未完待续)