1 vector
1.1 vector定义
vector是STL的动态数组,可以在运行中根据需要改变数组的大小。 以数组的形式储存,所以它的内存空间是连续的 进行 vector
操作前应添加头文件 #include <vector>
vector是向量类型,可以容纳许多类型的数据,因此也被称为容器
vector是种容器,类似数组一样,但它的size可以动态改变 。 vector的元素在内存中连续排列 ,这一点跟数组一样。这意味着我们元素的索引将非常快 ,而且也可以通过指针的偏移来获取vector中的元素。 连续排列也带来了弊端 ,当我们向vector中间插入一个数据时,整个vector的size变大,在内存中就需要重新分配空间; vector采用的做法是:vector会分配额外的空间 ,以适应size的动态增长 。 因此,包含同样数量元素的vector和数组相比,占用的空间会更大 。 在vector最后增加或者删除一个元素,消耗的时间是一个常数值,与vector的size无关。 与其他容器(deques
、lists
、forward_lists
)相比
优点:vector在获取元素和对最后一个元素的操作效率上更高; 缺点:但对于中间元素的操作,性能则相对较差。
1.2 vector初始化:
定义具有10个整型元素的向量
尖括号为元素类型名,它可以是任何合法的数据类型 不具有初值,其值不确定
vector< int > a ( 10 ) ;
定义具有10个整型元素的向量,且给出的每个元素初值为1
vector< int > a ( 10 , 1 ) ;
用向量b给向量a赋值,a的值完全等价于b的值
vector< int > a ( b) ;
将向量b中从0~2(共三个)的元素赋值给a,a的类型为int型
vector< int > a ( b. begin ( ) , b. begin+ 3 ) ;
从数组中获得初值
int b[ 7 ] = { 1 , 2 , 3 , 4 , 5 , 6 , 7 } ;
vector< int > a ( b, b+ 7 ) ;
1.2 二维vector初始化:
vector还支持二维数组,但这种二维数组是通过嵌套的方式来实现
vector< vector<int> > b(10, vector<int>(5));
vector< vector<int> > b(10, vector<int>(5, 0)) ;
vector<vector>dp(m,vector(n,1)); // 将dp初始化为m行n列的vector,初始化数值为1 //创建一个10*5的int型二维向量,其值全为0
vector< vector< int >> arr ( 3 ) ;
for ( int i = 0 ; i < 3 ; ++ i) {
arr[ i] . resize ( 3 ) ;
}
for ( int i = 0 ; i < 3 ; ++ i)
for ( int k = 0 ; k < 3 ; ++ k)
arr[ i] [ k] = i * k;
arr. resize ( 4 ) ;
arr[ 2 ] . resize ( 5 ) ;
插入元素
若想定义A = [[0,1,2],[3,4,5]],则: A.push_back里必须是vector
vector< vector< int > > A;
vector< int > B;
B. push_back ( 0 ) ;
B. push_back ( 1 ) ;
B. push_back ( 2 ) ;
A. push_back ( B) ;
B. clear ( ) ;
B. push_back ( 3 ) ;
B. push_back ( 4 ) ;
B. push_back ( 5 ) ;
A. push_back ( B) ;
vector< vector< int > > A;
A[ 0 ] . push_back ( 0 ) ;
A[ 0 ] . push_back ( 1 ) ;
A[ 0 ] . push_back ( 2 ) ;
A[ 1 ] . push_back ( 3 ) ;
A[ 1 ] . push_back ( 4 ) ;
A[ 1 ] . push_back ( 5 ) ;
访问元素 vector< vector<int> > b(10, vector<int>(5));
b[0].first; 行数、列数
b.size() 就是”二维数组”的行数 b[0].size() 就是”二维数组”的列数
1.3 vector对象的常用内置函数
1.3.0 vector属性及操作
1.3.0.1 迭代程序 Iterators
名字 描述 begin 返回迭代器第一个元素的指针 end 返回指向迭代器最后一个元素的指针 rbegin 返回迭代器逆序第一个元素的指针 rend 返回迭代器逆序最后一个元素的指针 cbegin 返回常量迭代器的第一个元素的指针 cend 返回常量迭代器的最后一个元素的指针 crbegin 返回常量迭代器逆序的第一个元素的指针 crend 返回常量迭代器逆序的最后一个元素的指针 常量迭代器:
std:: vector< int > vec = { 1 , 2 , 3 , 4 , 5 } ;
std:: vector< int > :: const_iterator it;
for ( it = vec. begin ( ) ; it != vec. end ( ) ; ++ it) {
std:: cout << * it << " " ;
}
1.3.0.2 容量 Capactiy
名字 描述 size 返回当前vector使用数据量的大小 ma_size 返回vector最大可用的数据量 resize 调整vector中的元素个数 capactiy 返回vector中总共可以容纳的元素个数 empty 测试vector是否是空的 reserve 控制vector的预留空间 shrink_to_fit 减少capactiy的size的大小
size返回的是当前vector中有多少元素; max_size返回的是最大可用的数据量,这跟实际的硬件有关,但也并不是所有的内存空间都可用,比如下面程序中的运行的内存大x小为32GByte,但返回的结果是4GByte; capacity是当前vector分配的可以容纳的元素个数,下面的代码中,vec0可以容纳13个元素,但仅包含了size(即10)个元素,还有3个元素可以放进去,当再放入超过3个元素后,vec0就会被重新分配空间;所以,capacity始终大于等于size; resize把容器改为容纳n个元素。调用resize之后,size将会变为n;
当n<size时,容器尾部的元素会被销毁,capacity保持不变; 当size<n≤capacity时,新增加的元素都是0,capacity保持不变; 当n>capacity时,size和capacity同时变为n,新增加的元素都是0; empty比较简单,当vector为空时,返回1,不为空返回0; shrink_to_fit,去掉预留的空间,capacity与size保持一致
1.3.0.3 元素访问Element access
名字 描述 operator[] 在[]中可以做运算 at vector.at(i)相当于vector[i] front 返回第一个元素的值 back 返回最后一个元素的值 data 返回指向vector内存数据的指针
1.3.0.4 修改器Modifiers
名字 描述 assign 指定vector内容 push_back 在容器的最后一个位置插入元素x pop_back 删除最后一个元素 insert 插入元素 erase 擦除元素 swap 交换两个容器的内容 clear 将容器里的内容清空,size值为0,但是存储空间没有变 emplace 插入元素(与insert有区别) emplace_back 在容器的最后一个位置插入新元素x(与push_back有区别)
有插入元素功能的函数有四个:push_back
、insert
、emplace
和emplace_back
,
emplace_back是在C++11中引入的,用法跟push_back完全一样,都是在vector的最后插入一个元素。
vec3.emplace_back(100);
底层实现方式不同
push_back
向容器尾部添加元素时,然后再将这个元素拷贝或者移动到容器中(如果是拷贝的话,事后会自行销毁先前创建的这个元素);emplace_back 在实现时,则是直接在容器尾部创建这个元素,省去了拷贝或移动元素的过程。
insert和emplace(C++11中引入)都可以向vector中间插入元素,但insert可以插入多个元素 ,emplace一次只能插入一个元素 。
vec1.insert(vec1.begin(), arr, arr + 5); vec1.insert(it, 3, 20); vec2.insert(it2, vec3.begin(), vec3.end()); emplace的使用方式为:
iterator emplace (const_iterator pos, args…); vector<int> vec0{1,2,3}; vec0.emplace(vec0.begin()+2,10); //[1,2,10,3]
vector中有三种可以删除元素的操作
pop_back,删除最后一个元素,无返回值; clear,将容器清空,size变为0,无返回值; erase,通过迭代器来删除元素,可以删除一个元素,也可以删除某个范围内的元素,返回下一个位置的迭代器。
1.3.0.5 分配器Allocator
名字 描述 get_allocator 返回vector的内存分配器
get_allocator用的不是特别多,我们把使用方法讲一下。
vector< int > myvector;
int * p;
unsigned int i;
p = myvector. get_allocator ( ) . allocate ( 5 ) ;
for ( i= 0 ; i< 5 ; i++ ) myvector. get_allocator ( ) . construct ( & p[ i] , i) ;
std:: cout << "The allocated array contains:" ;
for ( i= 0 ; i< 5 ; i++ ) std:: cout << ' ' << p[ i] ;
for ( i= 0 ; i< 5 ; i++ ) myvector. get_allocator ( ) . destroy ( & p[ i] ) ;
myvector. get_allocator ( ) . deallocate ( p, 5 ) ;
1.3
# include <vector>
vector< int > a, b;
1.3.1 assign( , ) :将b向量的0-2个元素赋值给向量a
a. assign ( b. begin ( ) , b. begin ( ) + 3 ) ;
1.3.2 assign( , ) :将4个值为2的元素赋值给a向量
a. assign ( 4 , 2 ) ;
1.3.3 back() :返回a的最后一个元素
a. back ( ) ;
1.3.4 a[i] :返回a的第i个元素,当且仅当a存在
a[ i] ;
1.3.5 clear() :清空a中的元素
a. clear ( ) ;
1.3.6 empty() :判断a是否为空,空则返回true,非空则返回false
a. emptry ( ) ;
1.3.7 pop_back() :删除a向量的最后一个元素
a. pop_pack ( ) ;
1.3.8 erase( , ) :删除a中第一个(从0个算起)到第二个元素
- 也就是说删除的元素从a.begin()+1算起(包括它)
- 不包括a.begin()+3
a. erase ( a. begin ( ) + 1 , a. begin ( ) + 3 ) ;
1.3.9 push_back :在a向量的最后一个向量后插入一个元素,其值为5
a. push_back ( ) ;
1.3.10 insert(postion, value) :在a的第一个元素位置(从第0个位置算起)插入数值5
a. insert ( a. begin ( ) + 1 , 5 ) ;
1.3.11 insert(position, n, value) :在a的第一个元素位置(从第0个算起)插入3个数,其值为5
a. insert ( a. begin ( ) + 1 , 3 , 5 ) ;
1.3.12 insert(position, b+3, b+6) :在a的第一个元素位置(从第0个算起)插入b向量的第三个元素到第5个元素(不包括b+6)
a. insert ( a. begin ( ) + 1 , b+ 3 , b+ 6 ) ;
1.3.13 size() :返回a中元素的个数
a. size ( ) ;
1.3.14 capacity() :返回a在内存中总共可以容纳的元素个数
a. capacity ( ) ;
1.3.15 resize(n) :将a的现有元素个数调整至10个,多则删,少则补,其值随机
a. resize ( 10 ) ;
1.3.16 resize(n) :将a的现有元素个数调整至10个,多则删,少则补,其值为2
a. resize ( 10 , 2 ) ;
1.3.17 reserve(n) :将a的容量扩充至n
a. reserve ( 100 ) ;
1.3.18 a.swap(b) :将a中的元素和b中的元素整体交换
a. swap ( b) ;
1.3.19 == != >= > <= < :向量的比较操作
a== b;
2 顺序访问vector的机中方式
2.1对向量a添加元素的几种方式
向向量a中添加元素
vector< int > a;
for ( int i= 0 ; i< 10 ; ++ i) { a. push_back ( i) ; }
从数组中选择元素向向量中添加
int a[ 6 ] = { 1 , 2 , 3 , 4 , 5 , 6 } ;
vector< int > b;
for ( int i= 0 ; i<= 4 ; ++ i) { b. push_back ( a[ i] ) ; }
从现有向量中选择元素向向量中添加
int a[ 6 ] = { 1 , 2 , 3 , 4 , 5 , 6 } ;
vector< int > b;
vector< int > c ( a, a+ 4 ) ;
for ( vector< int > :: iterator it= c. begin ( ) ; it< c. end ( ) ; ++ it)
{
b. push_back ( * it) ;
}
从文件中读取元素向向量中添加
ifstream in ( "data.txt" ) ;
vector< int > a;
for ( int i; in>> i) { a. push_back ( i) ; }
常见错误赋值方式
下标只能用来获取已经存在的元素,不能用来赋值
vector< int > a;
for ( int i= 0 ; i< 10 ; ++ i) { a[ i] = i; }
2.2 从向量中读取元素
通过下标方式获取
int a[ 6 ] = { 1 , 2 , 3 , 4 , 5 , 6 } ;
vector< int > b ( a, a+ 4 ) ;
for ( int i= 0 ; i<= b. size ( ) - 1 ; ++ i) {
cout<< b[ i] << endl;
}
通过迭代器方式读取
int a[ 6 ] = { 1 , 2 , 3 , 4 , 5 , 6 } ;
vector< int > b ( a, a+ 4 ) ;
for ( vector< int > :: iterator it= b. begin ( ) ; it!= b. end ( ) ; it++ ) {
cout<< * it<< " " ;
}
3 几个常用的算法
# include <algorithm>
3.1 sort(a.begin, a.end)
对a中的从a.begin()(包括它)到a.end()(不包括它)的元素进行从小到大排列
sort ( a. begin ( ) , a. end ( ) ) ;
sort ( a. begin ( ) , a. end ( ) , cmp) ;
bool cmp ( int para1, int para2)
{
return a> b;
}
3.2 reverse(a.begin(), a.end())
对a中的从a.begin()(包括它)到a.end()(不包括它)的元素倒置,但不排列,如a中元素为1,3,2,4,倒置后为4,2,3,1
reverse ( a. begin ( ) , a. end ( ) ) ;
3.3 copy(a.begin(), a.end(), b.begin()+1)
把a中的从a.begin()(包括它)到a.end()(不包括它)的元素复制到b中,从b.begin()+1的位置(包括它)开始复制,覆盖掉原有元素
copy ( a. begin ( ) , a. end ( ) , b. begin ( ) + 1 ) ;
3.4 find(a.begin(), a.end(), 100)
在a中的从a.begin()(包括它)到a.end()(不包括它)的元素中查找10,若存在返回其在向量中的位置
find ( a. begin ( ) , a. end, 10 ) ;
4 pair 结合 vector
4.1 pair:一对值可以具有不同的数据类型
pair< string , int > p;
make_pair ( x, y)
4.2 定义使用pair的vector:
vector< pair< string, int >> vec; 定义使用pair的vector:
vec. push_back ( make_pair ( x, y) ) ;
vec[ i] . first
vec[ i] . second
4.3 结合sort函数
static bool cmp ( pair< string, int > & a, pair< string, int > & b)
{
if ( a. second == b. second) {
return a. first < b. first;
}
return a. second > b. second;
}
sort ( vec. begin ( ) , vec. end ( ) , cmp) ;
4.4 结合map,vector和pair
for ( it = map. begin ( ) ; it!= map. end ( ) ; ++ it)
{
temp. push_back ( make_pair ( it-> first, it-> second) ) ;
}
4.5 利用set为vector去重(vec.assign(set.begin(),set.end()))
vec = { 1 , 2 , 3 , 4 , 8 , 9 , 3 , 2 , 1 , 0 , 4 , 8 } ;
set< int > st ( vec. begin ( ) , vec. end ( ) ) ;
vec. assign ( st. begin ( ) , st. end ( ) ) ;
参考文献
1、会敲代码的地质汪 2、浪迹天涯@wxy