c++常见容器
🏅vector
vector的构建
//默认无参构造,此时v无法通过[]操作符访问,会造成内存访问越界
std::vector<int> v;
//预申请内存方式构建,此时v可以通过[]操作符访问
std::vector<int> v(4);
//区间拷贝构造
std::vector<int> v1 = {1,2,3,4};
std::vector<int> v2(v1.begin(),v1.end());
//拷贝构造
std::vector<int> v1 = {1,2,3,4};
std::vector<int> v2(v1);
//n-num构造方式
std::vector<int> v(10,100) //构建10个100的vector
//assign方法
std::vector<int> v;
v.assign(v1.begin(),v1.end());
v.assign(10,100)
vector元素的增加删除
std::vector<int> v;
//尾部插入
v.push_back(2);
//尾部删除
v.pop_back();
//随机位置插入,提供迭代器插入位置
v.insert(v.begin(),100);
//随机位置插入n个元素
v.insert(v.begin(),2,100);
//随机位置擦除,提供迭代器擦除位置
v.erase(v.begin());//擦除到迭代器位置以前的所有元素
v.erase(v.end());//错误异常用法,删除尾部元素应该使用v.pop_back()函数
//随机区间擦除,提供迭代器位置区间
v.erase(v.begin(),v.end()); //此时相当于清空操作类似v.clear();
std::vector::clear与std::vector::resize
//c++先clear()再resize()会直接报错
std::vector<int> vec;
vec.clear();
vec.resize(); //error
vector 自定义排序问题
//自定义升序排序函数
auto compareFuc = [](_type_def& a,_type_def& b){
return a>b;
};
//自定义降序排序函数
auto compareFuc = [](_type_def& a,_type_def& b){
return a>b;
};
//sort 函数
std::sort(vec.begin(),vec.end(),compreFuc)
🏅deque
双端队列容器,与vector类似,可以在头部和尾部方便的插入删除元素,deque不能保证所有元素存储在一个连续的内存空间中
构建方式
#include <deque>
#include <iostream>
int main()
{
std::deque<int> a;//声明一个空的双端队列
std::deque<int> a(4);//声明一个4元素大小的双端队列
std::deque<int> a(4,1);//声明一个4个元素大小的双端队列,指定每个元素的值
std::deque<int> b(a);//拷贝构造
std::deque<int> b(a.begin(),a.end());//指定区间的拷贝构造
//从数组构造
int a[] = {1,2,3,4,5};
std::deque<int> b(a,a+5);
return 0;
}
增加删除
std::deque<int> d;
d.push_back(1); // 尾部插入元素
d.push_front(1);// 头部插入元素
d.pop_back();// 尾部删除元素
d.pop_front();// 头部删除元素
//随机位置插入
d.insert(d.begin()+1,1); //begin()+1位置插入一个元素1
d.insert(d.begin()+1,2,1); //begin()+1位置插入2个元素1
//随机位置删除
d.erase(d.begin()+2); //删除begin()+2位置的元素
d.erase(d.begin()+2,d.end());//删除begin()+2,end()之间的元素
//赋值 assign
d.assign(2,1);
🏅queue
先进先出队列
构建函数
#include <queue>
std::queue<int> a; //默认构造函数构建
std::queue<int> b(a); //拷贝构造函数构建
增加删除元素
#include<queue>
std::queue<int> a;
a.push(1);//队列入队1个元素
std::cout<<a.size()<<std::endl;//输出1
//pop
a.pop();//出队一个元素
std::cout<<a.size()<<std::endl;//输出0
//获取队首元素
int s = a.front();
//清空队列
while(!a.empty()){
a.pop();
}
🏅list
链表在对数据进行插入和删除是比顺序存储的线性表有优势,
因此在插入和删除操作频繁的应用场景中,
使用list和forward_list比使用array、vector和deque效率要高很多。
list为双向链表
forward_list是单向链表
#include <forward_list>
#include <list>
int main()
{
//std::list<int> l = {1,2,3,4,5};
std::forward_list<int> numbers = {1,2,3,4,5,4,4};
std::cout << "numbers:" << std::endl;
for (auto number : numbers)
{
std::cout << number << std::endl;
}
numbers.remove(4);
std::cout << "numbers after remove:" << std::endl;
for (auto number : numbers)
{
std::cout << number << std::endl;
}
//链表的插入删除元素
l.push_back(1); // 尾部插入元素
l.push_front(1); // 头部节点元素
l.emplace_back(1); // 右值尾部插入,避免对象的拷贝消耗
l.emplace_front(1); // 右值头部插入
l.pop_back(); // 尾部弹出元素
l.pop_front(); // 头部弹出元素
//擦除元素
l.erase(l.begin()+1); // l.begin()+1擦除该元素
l.erase(l.begin()+1,l.end()); // 擦除l.begin()+1到l.end()之间的元素
return 0;
}
🏅array
std::array是c++11新增的静态数组类
#include <array>
int main()
{
//构建方式
//std::array<int,4> arrayDemo{{1,2,3,4}};
std::array<int, 4> arrayDemo = { 1,2,3,4 };
std::cout << "arrayDemo:" << std::endl;
for (auto itor : arrayDemo)
{
std::cout << itor << std::endl;
}
int arrayDemoSize = sizeof(arrayDemo);
std::cout << "arrayDemo size:" << arrayDemoSize << std::endl; // 4*4 =16
return 0;
//arrayDemo.front() 获取数组首部元素
//arrayDemo.back() 获取数组尾部元素
//std::array重载了[]操作符,支持arrayDemo[i]访问
}
🏅set
std::unordered_set的数据存储结构也是哈希表的方式结构,
除此之外,std::unordered_set在插入时不会自动排序,这都是std::set表现不同的地方。
#include <iostream>
#include <string>
#include <unordered_set>
#include <set>
int main()
{
std::unordered_set<int> unorder_set;
unorder_set.insert(7);
unorder_set.insert(5);
unorder_set.insert(3);
unorder_set.insert(4);
unorder_set.insert(6);
std::cout << "unorder_set:" << std::endl;
for (auto itor : unorder_set)
{
std::cout << itor << std::endl; // 无序,不会排序,按插入的循序打印 7,5,3,4,6
}
std::set<int> set; // 有序,在插入时会自动排序
set.insert(7);
set.insert(5);
set.insert(3);
set.insert(4);
set.insert(6);
std::cout << "set:" << std::endl;
for (auto itor : set)
{
std::cout << itor << std::endl;// 有序3,4,5,6,7
}
}
🏅map
std::unordered_map与std::map用法基本差不多,但STL在内部实现上有很大不同
std::map使用的数据结构为二叉树,而std::unordered_map内部是哈希表的实现方式,
哈希map理论上查找效率为O(1)。但在存储效率上,哈希map需要增加哈希表的内存开销。
#include <iostream>
#include <string>
#include <unordered_map>
#include <map>
int main()
{
std::unordered_map<std::string, std::string> mymap =
{
{ "house","maison" },
{ "apple","pomme" },
{ "tree","arbre" },
{ "book","livre" },
{ "door","porte" },
{ "grapefruit","pamplemousse" }
};
unsigned n = mymap.bucket_count();// 使用的内存桶数量
std::cout << "mymap has " << n << " buckets.\n";
for (unsigned i = 0; i<n; ++i) // 遍历每一个桶,每个桶内可能存在多个数据
{
std::cout << "bucket #" << i << " contains: ";
for (auto it = mymap.begin(i); it != mymap.end(i); ++it)// 遍历每个桶内存储的数据
std::cout << "[" << it->first << ":" << it->second << "] ";
std::cout << "\n";
}
return 0;
}
🏅algothrim
头文件:
非修改序列算法
- find
- find_if
- find_first_of
- for_each
- count
- count_if
- search
- search_n
- find_end
⏰代码演示如下:
#include <algothrim>
#include <vector>
#include <list>
//一元函数操作符
bool is3(int x)
{
return x==3;
}
auto is3_lambda = [](int x){return x==3;};
struct Is3
{
//重载()操作符
bool operator()(int x)
{
return x==3;
}
}
int main()
{
//---------------------------------------find--------------------------------------------------
std::vector<int> v = {1,2,3,4,5};
std::vector<int> c = {3,4};
//std::vector<int>::iterator iter = std::find(v.begin(),v.end(),3);
auto iter = std::find(v.begin(),v.end(),3); //返回迭代器位置
if(iter!=v.end()){std::cout<<"找到"<<std::endl;}
//--------------------------------------find_if-------------------------------------------------
std::vector<int>::iterator iter = std::find_if(l.begin(),l.end(),is3); //调用函数对象
std::vector<int>::iterator iter = std::find_if(l.begin(),l.end(),is3_lambda); //调用lambda匿名函数对象
std::vector<int>::iterator iter = std::find_if(l.begin(),l.end(),Is3());//调用仿函数对象
if(iter!=l.end()){std::cout<<"找到"<<std::endl;}
//------------------------------------find_first_of---------------------------------------------
auto iter = std::find_first_of(v.begin(),v.end(),c.begin(),c.end()); //c与v只要有一个元素匹配则返回该元素的位置
auto isMod = [](int x,int s){
if(x%s==0) return 1;
else return 0;
}
auto iter = std::find_first_of(v.beign(),v.end(),c.beign(),v.end(),isMod);//返回两个序列整除的第一个数字所在位置即v序列中3的位置
if(iter!=v.end()){
std::cout<<"找到,位于v:"<<std::distance(v.begin(),iter)<<std::endl;
}
//----------------------------------------find_end----------------------------------------------
//std::find_end用于查找容器内子序列最后一次出现的位置,类似于find和finf_of,可接受一个二元操作符函数作为Pred
std::vector<int> v1 = {1,2,3,4,5,6,7,8};
std::vector<int> v2 = {4,5,6}; //子序列
auto result = std::find_end(v1.beign(),v1.end(),v2.begin(),v2.end());
if(result!=v1.end()){
std::cout<<"找到子序列位置:"<<std::distance(v1.begin(),result)<<std::endl;
}
auto equal_lambda = [](int a,int b){return a==b;}
auto result = std::find_end(v1.begin(),v1.end(),v2.begin(),v2.end(),equal_lambda);//调用自定义pred函数进行子序列匹配查询
if(result!=v1.end()){
std::cout<<"找到子序列位置:"<<std::distance(v1.begin(),result)<<std::endl;
}
//----------------------------------------for_each-----------------------------------------------
// for_each 类似python语法中的map函数
std::vector<int> a = {1,2,3,4,5};
auto lambdaPrint = [](int const& s){std::cout<<s<<" ";}
std::for_each(a.cbegin(),c.cend(),lambdaPrint); //逐个元素打印输出
struct Sum
{
int sm{0};
void operator()(int x){
sm+=x;
}
int getSum(){
return sm;
}
}
std::for_each(a.begin(),a.end(),Sum()); //累加
//------------------------------------------count------------------------------------------------
std::vector<int> a = {1,2,3,4,5,6,7,8,9};
const int num = std::count(a.cbegin(),c.cend(),4);//查找值为4的元素个数
//----------------------------------------count_if-----------------------------------------------
std::vector<int> a = {1,2,3,4,5,6,7,8,9};
const int num = std::count_if(a.cbegin(),a.cend(),[](const int x){return x%4==0;}); //查找被4整除的元素个数
//-----------------------------------------search------------------------------------------------
std::vector<int> a = {1,2,3,4,5,6,7,8,9};
std::vector<int> b = {3,4,5};
auto result = std::search(a.beign(),a.end(),b.begin(),be.end()); //查询子序列b在a中的位置
if(result != a.end())
{
std::cout<<"子序列位置找到"<<std::distance(a.begin(),result)<<std::endl;
}
//二元谓词
auto compare = [](int aa,int bb){
if(aa>bb) return 1;
else return 0;
}
auto result = std::search(a.beign(),a.end,b.begin(),b.end(),compare); // 查找比子序列b大的序列位置
}
修改序列算法
- random_shuffle 随机打乱指定范围内元素位置
- replace 将容器中指定元素的值替换为指定值
- replace_if 类似于replace
- replace_copy 与replace类似,同时将容器中元素拷贝到另一个容器
- fill && fill_n 给定范围内的元素赋值为指定值
- remove 将一个范围中值等价于给定值的元素删除、并返回新结尾迭代器
- reverse 反转排序指定范围内的元素
- unique 删除指定范围中的所有连续重复元素,仅仅留下每组等值元素中的第一个元素
- transform 对范围中的每个元素调用某函数,并将新值复制到另一个范围
- copy && copy_if
代码演示如下:
#include <iostream>
#include <vector>
#include <algothrim>
#include <iterator>
int main()
{
std::vector<int> a = {1,2,3,4,5,6};
//-------------------------------------------random_shuffle
std::random_shuffle(a.begin(),b.end()); //随机乱序整个序列a
std::for_each(a.begin(),a.end(),[](int x){std::cout<<x<<" ";}); // 打印乱序后的序列
std::cout<<std::endl;
//-------------------------------------------replace
std::replace(a.begin(),a.end(),3,55);//替换所有元素值为3的元素为55,a = {1,2,55,4,5,6}
std::for_each(a.begin(),a.end(),[](int x){std::cout<<x<<" ";}); // 打印替换后的元素序列
std::cout<<std::endl;
//-------------------------------------------replace_if
std::replace_if(a.begin(),b.end(),[](int x){return x%4==0;},66); //匿名一元谓词返回为true的位置替换为66,a={1,2,3,66,5,6}
std::for_each(a.begin(),a.end(),[](int x){std::cout<<x<<" ";}); // 打印结果
std::cout<<std::endl;
//-------------------------------------------replace_copy
//此时类似于replace只是将替换后的序列拷贝到另一个容器中
std::replace_copy(a.begin(),a.end(),std::ostream_iterator<int>(std::cout," "),3,22);
std::cout<<"\n";
std::vector<int> b(a.begin(),a.end());
std::replace_copy(a.begin(),a.end(),b.begin(),3,22);
//-------------------------------------------replace_copy_if
/*
类似replace_copy,只是将指定值替换为一元谓词
*/
std::replace_copy_if(a.beign(),a.end(),std::ostream_iterator<int>(std::cout," "),[](int x){return x%6==0;},66);
std::cout<<"\n";
//-------------------------------------------fill && fill_n
std::fill(a.begin(),a.end(),-1); // a={-1,-1,-1,-1,-1,-1}
std::fill_n(a.begin(),2,-1); // a={-1,-1,3,4,5,6};
//-------------------------------------------remove && remove_if && remove_copy && remove_copy_if
auto newEnd = std::remove(a.beign(),a.end(),3); //删除指定值的元素,不改变容器大小,返回删除后的序列最后位置
std::for_each(a.begin(),newEnd,[](int x){std::cout<<x<<" ";});
std::cout<<std::endl;
std::string str2 = "Text\n with\tsome \t whitespaces\n\n";
auto newEnd = std::remove_if(str2.begin(),str2.end(),[](unchar x){return std::isspace(x);});//删除字符串str2中的空格
/*
remove_copy类似于remove,移除指定元素后拷贝到指定容器中
*/
std::vector<int> b(a.size());
std::remove_copy(a.begin(),a.end(),b.begin(),3);//移除所有元素3并将移除后的序列拷贝到容器b中
/*
remove_copy_if类似与remove_if根据一元谓词结果删除特定元素后拷贝到另一个容器中
*/
std::remove_copy_if(a.begin(),a.end(),b.beign(),[](int x){return x%2==0;});//删除所有能被2整除的元素并将删除后的新序列拷贝到b中
//-------------------------------------------reverse && reverse_copy
std::vector<int> v{1, 2, 3};
std::reverse(v.begin(), v.end());
for (auto e : v)
std::cout << e;
std::cout << '\n';
int a[] = {4, 5, 6, 7};
std::reverse(std::begin(a), std::end(a));
for (auto e : a)
std::cout << e;
/*
reverse_copy类似reverse,只是将反序后的序列拷贝到另一个容器中
*/
std::vector<int> vv = {1,2,3,4,56};
std::vector<int> des(vv.size());
std::reverse_copy(vv.begin(),vv.end(),des.begin());
return 0;
//-------------------------------------------unique && unique_copy
std::vector<int> a = {1,1,2,3,4,4,5,6,5,5};
auto nEnd = std::unique(a.begin(),a.end()); //不改变a序列长度 a={1,2,3,4,5,6,5,0}
a.erase(nEnd,a.end()); //擦除尾部元素 a={1,2,3,4,5,6,5}
/*
unique_copy 类似unique,去重后将去重后的新序列拷贝到新序列中
*/
std::vector<int> b(a.size());
std::unique_copy(a.begin(),a.end(),b.begin()); // 第一种使用方法
std::unique_copy(a.beign(),a.end(),b.beign(),[](int aa,int bb){return aa==1 && bb==1;});
//-------------------------------------------transform
auto add1 = [](int x){return x+1;}
std::vector<int>des(a.size());
std::transform(a.begin(),a.end(),des.begin(),add1); //所有元素+1并拷贝到新序列des中
//-------------------------------------------copy && copy_if
/*
实现容器之间的数据copy作用
*/
std::vector<int> bb(a.size());
std::copy(a.begin(),a.end(),bb.beign());//单纯容易元素拷贝操作
bb.clear();//清空bb容器
std::copy_if(a.begin(),a.end(),std::back_inserter(bb),[](int x){return x==3;});//按照一元谓词返回结果拷贝元素
}
本文来自博客园,作者:DumoIO,转载请注明原文链接:https://www.cnblogs.com/dumoio/p/17627099.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)