【STL】C++标准模板库——vector

01、文章目录

02、浅谈Vector

Vectors 包含着一系列连续存储的元素,其行为和数组类似。访问Vector中的任意元素或从末尾添加元素都可以在常量级时间复杂度内完成,而查找特定值的元素所处的位置或是在Vector中插入元素则是线性级时间复杂度

  • 常量级时间复杂度:如果一个算法的时间复杂度是O(1)就称为常量级
  • 线性级时间复杂度:如果一个算法的时间复杂度是O(n)就称为线性级。

例如:
对于函数f(n),当不管n的大小为多少,f(n)的运行时间均为固定的时间T(n),则称为常量级的。
若对于f(n1),有运行时间为T(n1),但对于n2=Kn1,有运行时间为T(n2) = KT(n1),则称为线性级的。

从整体上来说,时间为常量级的算法的运行时间与输入的数据规模无关,而线性级的运行时间与输入规模呈线性关系。

03、Vector成员方法表

函数(Function)描述(Descriptioon)
vector<数据类型>构造函数
Operators对vector进行赋值或比较
assign()对Vector中的元素赋值
at()返回指定位置的元素
back()返回最末一个元素
front()返回第一个元素
begin()返回第一个元素的迭代器
end()返回最末元素的迭代器(译注:实指向最末元素的下一个位置)
capacity()返回vector所能容纳的元素数量(在不重新分配内存的情况下)
clear()清空所有元素
empty()判断Vector是否为空(返回true时为空)
erase()删除指定元素
get_allocator()返回vector的内存分配器
insert()插入元素到Vector中
max_size()返回Vector所能容纳元素的最大数量(上限)
pop_back()移除最后一个元素
push_back()在Vector最后添加一个元素
rbegin()返回Vector尾部的逆迭代器
rend()返回Vector起始的逆迭代器
reserve()设置Vector最小的元素容纳数量
resize()改变Vector元素数量的大小
size()返回Vector元素数量的大小
swap()交换两个Vector

04、浅谈Vector成员方法

4.1 构造函数(vector)

Syntax:

#include <vector> //使用vector必须包含此头文件,后面的方法,我省略,但是写程序不能省略

vector<int> vec; //构造一个int类型vector容器,名字叫vec
//或者
vector<int> vec(10,0); //构造了一个容量为10,初始值都为0的int类型vector容器,

vector<int> b(4,3);
vector<int> a(b); //用容器b整体复制性赋值容器a

vector<int> a(b.begin(),b.begin()+3); //赋值前3个元素

int tmp[7] = {1,2,3,4,5,6,7}; //数组tmp,int类型数组
vector<int> a(tmp,tmp+7);  //从数组中的元素给向量vector赋值

C++ Vectors可以使用以下任意一种参数方式构造:

  • 无参数 - 构造一个空的vector,
  • 数量(num)和值(val) - 构造一个初始放入num个值为val的元素的Vector
  • vector(from) - 构造一个与vector from 相同的vector
  • 迭代器(start)和迭代器(end) - 构造一个初始值为[start,end)区间元素的Vector(注:半开区间).
4.2 运算符(Operators)

Syntax:

vector<int> v1,v2;
//运算符如下:
v1 == v2
v1 != v2
v1 <= v2
v1 >= v2
v1 < v2
v1 > v2 
v[]

C++ Vectors能够使用标准运算符: ==, !=, <=, >=, <, 和 >. 要访问vector中的某特定位置的元素可以使用 [] 操作符.

两个vectors被认为是相等的,如果:

  1. 它们具有相同的容量
  2. 所有相同位置的元素相等.
4.3 assign()函数

Syntax:

vector<int> v1;
vector<int> v2(4,7);

//两种方式
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);

//此for写法,待会说
for(int i : v1)
{
	cout << "v1:" << i << endl; //1,2,3
}

v1.assign(3,9); //将三个9赋值给v1
for(int j : v1)
{
	cout << "v1:" << j << endl; //9,9,9
}

v1.assign(v2.begin(),v2.begin()+3);
for(int k : v1)
{
	cout << "v1:" << k << endl; //7,7,7
}

assign() 函数要么将区间[start, end)的元素赋到当前vector,或者赋num个值为val的元素到vector中.这个函数将会清除掉为vector赋值以前的内容.

4.4 at()函数

Syntax:

TYPE at( size_type loc );
//at() 函数 返回当前Vector指定位置loc的元素的引用. at() 函数 比 [] 运算符更加安全, 因为它不会让你去访问到Vector内越界的元素. 
//例如, 考虑下面的代码:
vector<int> v( 5, 1 );

for( int i = 0; i < 10; i++ )
{
  cout << "Element " << i << " is " << v[i] << endl;
}

//这段代码访问了vector末尾以后的元素,这将可能导致很危险的结果.以下的代码将更加安全:
vector<int> v( 5, 1 );

for( int i = 0; i < 10; i++ ) 
{
  cout << "Element " << i << " is " << v.at(i) << endl;
}

取代试图访问内存里非法值的作法,at() 函数能够辨别出访问是否越界并在越界的时候抛出一个异常.

4.5 back()函数与front()函数

Syntax:

 TYPE back();
 TYPE front();
//back() 函数返回当前vector最末一个元素的引用.
//front()函数返回当前vector起始元素的引用.
//例如:
vector<int> v;

for( int i = 0; i < 5; i++ ) {
  v.push_back(i);
}

cout << "v第一个元素是:" << v.front() << endl; //0
cout << "v最后一个元素是:" << v.back() << endl; //4
4.6 begin()函数与end()函数

Syntax:

iterator begin(); //begin()函数返回一个指向当前vector起始元素的迭代器.
iterator end(); //end() 函数返回一个指向当前vector末尾元素的下一位置的迭代器.注意,如果你要访问末尾元素,需要先将此迭代器自减1.

vector<int> v1( 5, 789 );
vector<int>::iterator it;
for( it = v1.begin(); it != v1.end(); it++ ) {
 cout << *it << endl;
 }
 
4.7 capacity()函数

Syntax:

size_type capacity(); //返回当前vector在重新进行内存分配以前所能容纳的元素数量.

//例如:
vector<char> vec;
vec.push_back('a');
vec.push_back('b');
vec.push_back('c');
vec.push_back('d');
vec.push_back('e');
vec.push_back('f');

cout << "vec的容量为:" << vec.capacity() << endl; //6
4.8 clear()函数

Syntax:

 void clear(); //删除(清空)当前vector中的所有元素.

//例如:
vector<int> v;
v.push_back(1);
v.push_back(2);

for(int i : v)
{
	cout << "v:" << i << endl;
}

v.clear(); 

cout << "打印j" <<endl;
for(int j : v)
{
	cout << j << endl; //里面啥都没有
}
cout << "打印完了" <<endl;
4.9 empty()函数

Syntax:

 bool empty(); //如果当前vector没有容纳任何元素,则empty()函数返回true,否则返回false.

//例如:
vector<int> vec;
vec.push_back(1);

if(!vec.empty())
{
	cout << "vec is't  Null" << endl; //有元素,肯定是走这里来
}

cout << "vec is Null" << endl;


//下面逆序打印
vector<int> v;
  
for( int i = 0; i < 5; i++ ) {
    v.push_back(i);
  }
  
while( !v.empty() ) {
    cout << v.back() << endl;
    v.pop_back(); 
  }
4.10 erase()函数

Syntax:

iterator erase( iterator loc );
iterator erase( iterator start, iterator end );

/*
erase函数要么删作指定位置loc的元素,要么删除区间[start, end)的所有元素.
返回值是指向删除的最后一个元素的下一位置的迭代器.
*/

// 创建一个vector,置入字母表的前十个字符
vector<char> alphaVector; 
for( int i=0; i < 10; i++ ) 
{
	alphaVector.push_back( i + 65 ); 
}
int size = alphaVector.size(); 
vector<char>::iterator startIterator; 
vector<char>::iterator tempIterator; 
for( int i=0; i < size; i++ ) 
{ 
	tartIterator = alphaVector.begin(); 
	alphaVector.erase( startIterator ); // Display the vector 
	for( tempIterator = alphaVector.begin(); tempIterator != alphaVector.end();tempIterator++) 
	{
		cout << *tempIterator; 
	}
	cout << endl;
}

这段代码将会显示如下输出:
BCDEFGHIJ
CDEFGHIJ
DEFGHIJ
EFGHIJ
FGHIJ
GHIJ
HIJ
IJ
J

4.11 get_allocator函数

Syntax:

 allocator_type get_allocator(); //函数返回当前vector的内存分配器.

//这里输出我用printf输出,不然要重载运算符,到时候聊重载运算符再以此为例
vector<int> vec;
for(int i = 0; i < 10; i++)
{
	vec.push_back(i+1);
}

printf("内存分配:%d\n",vec.get_allocator()); //204

至于为何是204,大家可以暂时不用管,我也是初学者,用不上的东西先搁一搁。

4.12 insert()函数

Syntax:

 iterator insert( iterator loc, const TYPE &val );
 void insert( iterator loc, size_type num, const TYPE &val );
 void insert( iterator loc, input_iterator start, input_iterator end );

/*
nsert() 函数有以下三种用法:
	1、在指定位置loc前插入值为val的元素,返回指向这个元素的迭代器,
	2、在指定位置loc前插入num个值为val的元素
	3、在指定位置loc前插入区间[start, end)的所有元素 .
*/

//例如:
//创建一个vector,置入字母表的前十个字符
vector<char> alphaVector;
for( int i=0; i < 10; i++ )
  alphaVector.push_back( i + 65 );

//插入四个C到vector中
vector<char>::iterator theIterator = alphaVector.begin();
alphaVector.insert( theIterator, 4, 'C' );

//显示vector的内容
for( theIterator = alphaVector.begin(); theIterator != alphaVector.end(); theIterator++ )
  cout << *theIterator;

这段代码将显示:

CCCCABCDEFGHIJ

4.13 max_size

Syntax:

size_type max_size(); //返回当前vector所能容纳元素数量的最大值(译注:包括可重新分配内存).

vector<int> v;
for(int i = 0; i < 4; i++)
{
	v.push_back(i);
}

cout << v.max_size(); << endl; //1073741823
4.14 size()函数

Syntax:

size_type size(); //返回当前vector所容纳元素的数目

vector<int> v;
for(int i = 0; i < 4; i++)
{
	v.push_back(i);
}

cout << v.size(); << endl; //4
4.15 resize()函数

Syntax:

void resize( size_type size, TYPE val ); //改变当前vector的大小为size,且对新创建的元素赋值val

vector<int> v;
for(int i = 0; i < 4; i++)
{
	v.push_back(i);
}

cout << v.size() << endl; //4
v.resize(6,9);
cout << v.size() << endl; //6
4.16 rbegin()函数与rend()函数

Syntax:

reverse_iterator rbegin(); //返回指向当前vector末尾的逆迭代器.(译注:实际指向末尾的下一位置,而其内容为末尾元素的值)
reverse_iterator rend(); //返回指向当前vector起始位置的逆迭代器.

与begin()函数与end()函数作用相反,所以这里不举例了。

4.17 swap()函数

Syntax:

void swap( vector &from );  //swap()函数交换当前vector与vector from的元素

//如下所示:
vector<int> v;
for(int i = 0; i < 3; i++)
{
	v.push_back(i);
}

cout << "交换前:" <<endl;
for(int i : v)
{
	cout << i << " "; //0 1 2
}
cout<<endl;

vector<int> v1;
for(int i = 0; i < 3; i++)
{
	v1.push_back(i+3);
}

v.swap(v1);
cout << "交换后:" << endl;
for(int i : v)
{
	v.push_back(i); //3 4 5
}
4.18 push_back()函数

Syntax:

//这个函数从开始就一直在写,应该知道怎么用了吧
void push_back( const TYPE &val ); //添加值为val的元素到当前vector末尾

注意这里的值一定要和vector<数据类型>中的数据类型匹配

4.19 pop_back()函数

Syntax:

void pop_back(); //函数删除当前vector最末的一个元素,例如:

vector<char> alphaVector; 
for( int i=0; i < 10; i++ ) 
{
	alphaVector.push_back( i + 65 ); 
}
int size = alphaVector.size(); 
vector<char>::iterator startIterator; 
vector<char>::iterator tempIterator; 
for( int i=0; i < size; i++ ) 
{ 
	tartIterator = alphaVector.begin(); 
	alphaVector.erase( startIterator ); // Display the vector 
	for( tempIterator = alphaVector.begin(); tempIterator != alphaVector.end();tempIterator++) 
	{
		cout << *tempIterator; 
	}
	cout << endl;
}

这段代码将显示以下输出:

ABCDEFGHI
ABCDEFGH
ABCDEFG
ABCDEF
ABCDE
ABCD
ABC
AB
A

到此,关于STL——vector的所有函数都说完了。然后现在聊聊上一节string说的要提及的遍历方法。

05、容器遍历方法(结)

容器遍历方法,我这里总结了三种,两种普遍的,一种就是上面我经常使用的C++ 11中加入的区间迭代!

5.1 下标遍历法

此方法,应该是我们最熟悉的,从C语言学习数组开始就一直在用。

#include <iostream>
#include <vector> //vector头文件
using namespace std;

void Traverse(vector<int> &from)
{
	int len = from.size(); //获得vector当前元素个数
	for(int i = 0; i < len; i++)
	{
		cout << from[i] << endl;
	}
}

int main()
{
	vector<int> vec;
	vec.push_back(1);
	vec.push_back(2);
	vec.push_back(3);
	vec.push_back(4);
	vec.push_back(5);
	vec.push_back(6);
	
	Traverse(vec);
	
	system("pause");
	return 0;
}
5.2 迭代器遍历

这种方法,如果你看过我正则的内容,应该知道是啥。如果没有,现在一起来看看,我尽量说的详细点。

#include <iostream>
#include <vector> //vector头文件
using namespace std;

void Traverse(vector<int> &from)
{
	/*
		迭代器遍历是最原始的一种遍历方式,是底层提供给我们直接用的,而其他遍历方式,就是在迭代器上穿了一件衣服,可以这么理解哈。
	*/

	vector<int>::iterator start = from.begin(); //获取开始迭代器
	vector<int>::iterator end = from.end(); //获取结束迭代器

	//开始遍历
	for(vector<int>::iterator it = start; it != end; it++)
	{
		cout << *it << endl;
	}
}

int main()
{
	vector<int> vec;
	vec.push_back(1);
	vec.push_back(2);
	vec.push_back(3);
	vec.push_back(4);
	vec.push_back(5);
	vec.push_back(6);
	
	Traverse(vec);
	
	system("pause");
	return 0;
}
5.3 区间迭代(C++ 11新特性)

这种方法就是非常好用的,适合懒人用的遍历方法。 感觉C++ 11的那些新特性就是为懒而准备的便利方法.

#include <iostream>
#include <vector> //vector头文件
using namespace std;

void Traverse(vector<int> &from)
{
	//迭代遍历,一个一个录入到i
	for(int i : from)
	{
		cout << i << endl;
	}
}

int main()
{
	vector<int> vec;
	vec.push_back(1);
	vec.push_back(2);
	vec.push_back(3);
	vec.push_back(4);
	vec.push_back(5);
	vec.push_back(6);
	
	Traverse(vec);
	
	system("pause");
	return 0;
}

06、几种常用的算法

这里介绍几种常见的算法:排列(排序)、复制(拷贝)和替换、查找,算术生成、集合
下面介绍的算法有些需要包含头文件:algorithm
这里只做介绍,后面单独聊此处提及的算法.

6.1 排序算法
  • merge算法:容器元素合并,并存储到另一容器中
merge(iterator beg1, iterator end1, iterator beg2, iterator end2,iterator dest);
/*
@param beg1 容器1开始迭代器
@param end1 容器1结束迭代器
@param beg2 容器2开始迭代器
@param end2 容器2结束迭代器
@param dest 目标容器开始迭代器
*/
  • sort算法:容器元素排序(两个容器必须是有序的)
sort(iterator beg,iterator end, _callback);

/*
@param beg 容器开始迭代器
@param end 容器结束迭代器
@param _callback 回调函数或者谓词(返回bool类型的函数对象) 
*/

  • reverse算法:反转指定范围的元素
reverse(iterator beg, iterator end);

/*
@param beg 容器开始迭代器
@param end 容器结束迭代器
*/
6.2 拷贝和替换算法
  • copy算法:将容器内指定范围的元素拷贝到另一容器中
copy(iterator beg, iterator end, iterator dest);

/*
@param beg 容器开始迭代器
@param end 容器结束迭代器
@param dest 目标容器结束迭代器
*/
  • replace算法:将容器内指定范围的旧元素修改为新元素
replace(iterator begg, iterator end,oldvalue, newvalue);

/*
@param beg 容器开始迭代器
@param end 容器结束迭代器
@param oldvalue 旧元素
@param newvalue 新元素
*/
  • replace_if算法:将容器内指定范围满足条件的元素替换为新元素
replace_if(iterator beg, iterator end, _callback, newvalue)

/*
@param beg 容器开始迭代器
@param end 容器结束迭代器
@_callback 回调函数或者谓词(返回bool类型的函数对象)
@param newvalue 新元素
*/
  • swap算法:互换两个容器的元素
swap(container c1, coontainer c2);

/*
@param c1 容器1
@param c2 容器2
*/
6.3 查找算法

find(a.begin(),a.end(),10); //在a中的从a.begin()(包括它)到a.end()(不包括它)的元素中查找10,若存在返回其在向量中的位置

  • find算法:查找容器中的元素是否匹配要要找的元素
find(itreator start, itreator end, Type target);

/*
@param start 容器开始迭代器
@param end 容器结束迭代器
@param target 容器对应类型的值(要查找的值)
*/
6.4 算术生成算法
  • accumulate算法:计算容器元素累计总和
accumulate(iterator beg, iterator end, value t);

/*
@param beg 容器开始迭代器
@param end 容器结束迭代器
@param value t 累加值
*/
  • fill算法:向容器中添加元素
fill(iterator beg, iterator end, value t);

/*
@param beg 容器开始迭代器
@param end 容器结束迭代器
@param value t 填充元素
*/
6.5 集合算法
  • set_intersection算法:求两个set集合的交集
//注意:两个集合必须是有序序列
set_intersection(iterator beg1, iterator end1, iterator beg2, iterator end2 iterator dest);

/*
@param beg1 容器1开始迭代器
@param end1 容器1结束迭代器
@param beg2 容器2开始迭代器
@param end2 容器2结束迭代器
@param dest 目标容器开始迭代器
@return 目标容器的最后一个元素的迭代器地址
*/
  • set_union算法:求两个set集合的并集
//注意:两个集合必须是有序序列
set_union(iterator beg1, iterator end1, iterator beg2, iterator end2 iterator dest);

/*
@param beg1 容器1开始迭代器
@param end1 容器1结束迭代器
@param beg2 容器2开始迭代器
@param end2 容器2结束迭代器
@param dest 目标容器开始迭代器
@return 目标容器的最后一个元素的迭代器地址
*/
  • set_difference算法:求两个set集合的差集
//注意:两个集合必须是有序序列
set_union(iterator beg1, iterator end1, iterator beg2, iterator end2 iterator dest);

/*
@param beg1 容器1开始迭代器
@param end1 容器1结束迭代器
@param beg2 容器2开始迭代器
@param end2 容器2结束迭代器
@param dest 目标容器开始迭代器
@return 目标容器的最后一个元素的迭代器地址
*/

07、小结

vector容器是STL 中非常重要的容器,一定要掌握。
这里贴一个张表:

C/C++STL对应关系
数组vector容器类似等同关系,数据结构一样
链表list容器类似等同关系,数据结构一样

算法,我们就聊完list、set等容器之后再做一个总回顾吧,暂且放一放!

如果博主有什么地方不正确,请大家指出一下,谢谢。
版权声明:转载请注明出处,谢谢!

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Cain Xcy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值