注意:使用下列代码请include必要头文件
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
初始化和赋值方式
int main(){
//(1)初始化方式
// 列表初始化
vector<int> arr{1,2,3}; //arr={1,2,3}
//指定大小和初始值
vector<int> arr2(3,0); //arr2={0,0,0}
vector<vector<int>> arr_2d(2, vector<int>(3,0)); //二维向量arr_2d={{0,0,0},{0,0,0}}
//从其他向量中拷贝指定范围的元素
vector<int> arr3(arr.begin(), arr.end()); //arr3={1,2,3}
//(2) 给vector赋值
// 使用构造函数
vector<int> arr_c1 = arr; //arr_c1={1,2,3}
arr_c1 = {4,5,6}; //arr_c1={4,5,6}
return 0;
}
访问元素
int main(){
vector<int> arr{1,2,3,4,5,6,7};
//1、根据下标访问元素
arr[3]; //arr[3]=4
//2、根据迭代器访问元素
auto it = arr.begin(); //it->1 *it=1
it++; //it->2
it = arr.end(); //it指向vector末尾的随机访问迭代器
auto it_r = arr.rbegin(); //it->7
it_r = it_r + 2; //it->5
it_r = arr.rend(); //it指向反向矢量末尾的迭代器
return 0;
}
增-添加元素
int main(){
vector<int> arr{1,2,3};
//1、在尾部插入元素--介绍push_back和emplace_back
arr.push_back(4); //arr={1,2,3,4}
//或在尾部就地插入元素
arr.emplace_back(5); //arr={1,2,3,4,5}
//2、在指定位置插入元素--介绍insert
auto it_pos = arr.begin() + 2;
arr.insert(it_pos, 6); //arr={1,2,6,3,4,5}
//在指定位置批量插入元素
//如在it_pos位置处插入2个7
arr.insert(it_pos, 2, 7); //arr={1,2,7,7,6,3,4,5}
return 0;
}
这里解释下什么是就地构造元素,和普通添加元素有什么区别。
以push_back和emplace_back方法为例,同样是将元素插入末尾。当我们需要在末尾插入一个临时元素时,使用push_back会先构造一个临时对象,然后再将这个元素的值拷贝或移动进元素末尾;而emplace_back会在容器末尾直接构造一个元素,不会进行多余的拷贝或移动。见下列代码
class A { public: A(int n){ cout << "A structure" << endl; } A(const A& a){ cout << "A copy structure" << endl; } A(A&& a){ cout << "A move structure" << endl; } private: }; int main(){ vector<A> arr1, arr2; cout << " push back:" << endl; arr1.push_back(1); cout << " emplace back:" << endl; arr2.emplace_back(1); return 0; }
输出结果
可见,当我们需要在容器中添加一个新元素,并且可以通过构造函数的参数列表直接在容器中构造对象时,使用emplace_back是更为高效的选择。
但是我们如果想在元素末尾插入一个已经存在的对象时,使用puch_back和emplace_backd的表现都是一样的,都是会直接调用对象拷贝或移动构造函数来插入元素。见下代码
A a1(1), a2(2); vector<A> arr1, arr2; cout << " push back:" << endl; arr1.push_back(a1); cout << " emplace back:" << endl; arr2.emplace_back(a2);
输出:
A a1(1), a2(2); vector<A> arr1, arr2; cout << " push back:" << endl; arr1.push_back(std::move(a1)); cout << " emplace back:" << endl; arr2.emplace_back(std::move(a2));
输出:
所以,当需要插入一个已经存在的对象,使用push_back可能更简洁合适。
删除元素
int main(){
vector<int> arr{1,2,3,4,5,6,7};
//1、在尾部删除元素--介绍pop_back
arr.pop_back(); //arr={1,2,3,4,5,6}
//2、删除指定位置元素--介绍erase
auto it_pos = arr.begin() + 2;
//删除第3个元素,并返回了删除的后一个元素的迭代器
it_pos = arr.erase(it_pos); //arr={1,2,4,5,6}, it_pos->4
//3、批量删除元素
it_pos = arr.erase(it_pos, it_pos+2); //arr={1,2,6}, it_pos->6
//4、批量删除某元素--介绍遍历和使用remove函数
// (1)批量删除元素可以在遍历过程中使用erase逐个删除,比如删除arr2中的元素2
vector<int> arr2{1,2,3,4,2,5,7,6,7,2,5,8};
auto it2 = arr2.begin();
while(it2 != arr2.end())
{
if(*it2 == 2)
it2 = arr2.erase(it2);
else
++it2;
}
//结束后arr2={1,3,4,5,7,6,7,5,8}
//(2)使用remove函数
//remove可以从给定范围中删除指定值,而不影响剩余元素的顺序。返回没有指定值的新范围的结束位置。
//需要注意的是,remove处理过后的容器并没有完全将所需数值删除,而是移到了最后,结合remove的返回值(新范围的结束位置)将容器分成了“有效部分”和“无效部分”。需要使用earse删除无效部分。
auto it_new_end = std::remove(arr2.begin(), arr2.end(), 7);
//运行后发现arr2={1 3 4 5 6 5 8 5 8}还是9个元素,it_new_end指向arr2[7]
//需要根据返回的新最后位置,使用erase删除无效元素
arr2.erase(it_new_end, arr2.end()); //arr2={1 3 4 5 6 5 8}
//(3)根据条件批量删除元素--介绍remove_if
// remove_if需要传入一个条件谓词,可以使用匿名函数表达条件,返回值为bool,true代表条件满足(需要移除)
// remove_if的其他参数和返回值用法同remove
// 例题:删除数组中的奇数
arr2.erase(remove_if(arr2.begin(),arr2.end(),
[](int val){return val%2 != 0;}),
arr2.end());
// arr2={4 6 8}
return 0;
}
查找元素
vector类不带有查找某元素的成员方法,我们可以使用 algorithm 中的方法。
int main(){
vector<int> arr{1,2,3,4,5,6,7};
//1、查找某元素--介绍find(起始位置迭代器,结束位置迭代器,数值)
// 查找到-返回指向第一次出现该元素的迭代器
auto it = find(arr.begin(), arr.end(), 5); //it->5
// 查找某元素位置下标
int pos = distance(arr.begin(), it); // pos=4
// 没有查找到-返回find输入的结束位置迭代器
it = find(arr.begin(), arr.end(), 9); //arr中没有元素9 it=arr.end()
// 2、条件查找--介绍find_if(起始位置迭代器,结束位置迭代器,条件)
// 条件可以使用匿名函数,确保函数返回值为bool类型,true代表找到,返回指定迭代器;false代表未找到,返回结束位置迭代器
// 例如,查找第一个偶数
it = find_if(arr.begin(), arr.end(),
[](int val){return val%2==0;}); //it->2
return 0;
}
替换元素
int main(){
vector<int> arr{3,4,3,5,7};
//(1)替换指定元素
//例:将3替换成6
replace(arr.begin(), arr.end(),3,6); //arr={6,4,6,5,7}
//(2)按照条件替换
//例:将所有偶数替换成0
replace_if(arr.begin(), arr.end(),
[](int v){return v%2==0;}, 0);//arr={0,0,0,5,7}
return 0;
}
其他常用算法
int main(){
vector<int> arr{1,3,4,5,2};
//(1)求容器大小
int si = arr.size(); //si=5
//(2)反转容器中的元素
reverse(arr.begin(), arr.end()); //arr={2,5,4,3,1}
//(3)求元素最大值、最小值
auto it_max = max_element(arr.begin(), arr.end()); //it_max->5
auto it_min = min_element(arr.begin(), arr.end()); //it_min->1
//(4)交换容器中两个元素
swap(arr[2],arr[4]); //arr={2,5,1,3,4}
//(5)排序
//按照升序排列
sort(arr.begin(), arr.end()); //arr={1,2,3,4,5}
//按照降序排列
sort(arr.begin(),arr.end(),std::greater<int>()); //arr={5,4,3,2,1}
//std::greater<int>()是一个函数对象,是std::greater模版类的int特化,用于比较两个函数的大小关系,按照降序比较
//相对的,std::less<int>()是按照升序比较。sort函数默认是升序的
return 0;
}
【参考资料】