一、集合set
头文件<set>
1.特性:
????????①数据自带排序②没有重复(数据的唯一性)
2.基本操作:
????????①创建(第一个参数是存储数据的类型,第二个是排序准则)
set<int> setData; //默认方式 从小到大
set<int, less<int>> setData2; //和默认方式一样
set<int, greater<int>> setData3; //从大到小
????????②插入:insert(data)
setData.insert(temp);
????????③迭代器遍历
for (set<int>::iterator iter = setData.begin(); iter != setData.end(); iter++)
{
cout << *iter << " ";
}
3.对于自定义类型数据的处理:
????????核心问题:重载?第一行的less<····>是作为第二个的默认参数(下为set原型)
?而less即为从小到大? 所以我们需要重载<号 (其余同理) (注:一定要是常属性参数+常函数)
class wbm
{
public:
wbm(string name,int age):name(name),age(age){}
bool operator<(const wbm &temp)const
{
return name < temp.name;
}
void print()
{
cout << name << "\t" << age << endl;
}
protected:
string name;
int age;
};
void test_wbm_set()
{
wbm w1("wbm1", 11);
wbm w2("wbm2", 22);
wbm w5("wbm5", 55);
wbm w4("wbm4", 44);
wbm w3("wbm3", 33);
wbm temptest("wbm3", 99);
set<wbm> wbmset = { w1,w2,w3,w4,w5,temptest };
for (auto v : wbmset)
{
v.print();
}
}
输出结果:(很显然,temptest没有被插入进去)->查重标准是按照重载写的<准则(按照name进行比较的。
?二、多重集合multiset
1.特性:
????????只具有排序功能,不具有去重功能
2.写法同set
????????(不同点在于,multiset仅排序)
void testmultiset()
{
multiset<int> mulData;
for (int i = 0; i < 10; i++)
{
mulData.insert(rand() % 10);
//rand()%26+'A';
//rand()%26+'a';
}
for (auto v : mulData)
{
cout << v << " ";
}
cout << endl;
}
输出结果:0 1 2 4 4 4 7 8 8 9?
三、二进制集合bitset
头文件????????????????????????#include<bitset>
1.特性:(常用于二进制操作)
????????管理二进制的容器,不需要传类型(只需要传一个长度->代表有多少个二进制位)
2.常见功能
????????(详见F1微软在线文档,在网安和底层开发会很有用。)
3.简单实例:?
????????①两种构造方式:
? ? ? ? ? ? ? ? ? ? ? 以字符串的形式就是直接原封不动的去掉引号,变成二进制
? ? ? ? ? ? ? ? ? ? ? 以传入一个整数的形式,就是将该整数(十进制)转化为二进制再保存到容器中。
? ? ? ? ②flip():1和0的反转(~)? ?all():检测每一个位是否都是1 ????????any():检测是否有位含1?
void testmultiset()
{
//多个二进制位
bitset<8> bData("11110000");
cout << bData << endl;
bData.flip(); //等效于~
cout << bData << endl;
cout << bData.all() << endl;
cout << bData.any() << endl;
cout << bData.size() << endl;
cout << bData.none() << endl;
bitset<8> num(7); //将7转化为二进制的形式保存在bitset的容器中。
cout << num << endl;
}
?输出:
11110000 00001111 0 1 8 0 00000111
?四、映射map
1.map中存放的pair数据类型
????????????????->称为数对类型(将两个数据绑定到一起)
? ? ? ? ? ? ? ? ?实际上就是一个两个待实例化的模板结构体
? ? ? ? ? ? ? ? 访问方式:m_pair.first? ? m_pair.second 分别访问第一二个绑定的元素
template <class _Ty1, class _Ty2>
struct MyPair
{
_Ty1 first;
_Ty2 second;
MyPair(_Ty1 first, _Ty2 second) :first(first), second(second) {}
};
//map存储的数据是一个数对类型
void testPair()
{
pair<int, string> pData(1, "string");
MyPair<int, string> myPData(1, "string");
cout << pData.first << " " << pData.second << endl;
}
2.map的特性
? ? ? ? ①自带排序,默认是从小到大
? ? ? ? ②数据唯一性
3.基本操作
? ? ? ? ①插入:
? ? ? ? ? ? ? ? 方式一:insert一个数对类型(两个数值,first是键,second是值)
map<int,string> mapData;
mapData.insert(pair<int,string>(1,"string"));
? ? ? ? ? ? ? ? 方式二:insert通过一个make_pair函数构建
map<int,string> mapData;
mapData.insert(make_pair<int,string>(3,"string3"));
? ? ? ? ? ? ? ? 方式三:单映射中,可以直接采用数组下标的方式进行插入
map<int,string> mapData;
mapData[-1]=string("string-1");
?方式三的代码等效于:
? ? ? ? mapData.insert(pair<int,string>(-1,"string-1"));
?注:相同的键,是采用覆盖的方式(保留最后一次更新的值)
? ? ? ? ?②遍历:
? ? ? ? ? ? ? ? 方式一:迭代器遍历
? ? ? ? ? ? ? ? ? ? ? ? (注:这里的*iter是pair数对类型。)
for(auto iter=mapData.begin();iter!=mapData.end();iter++)
{
cout<<iter->first<<" "<<iter->second<<endl;
//*iter指的是pair类型。
}
? ? ? ? ? ? ? ? 方式二:
for(auto v:mapData)
{
cout<<v.first<<" "<<v.second<<endl;
}
? ? ? ? ?③删除erase():
? ? ? ? ? ? ? ? ? ? ?传入参数(是需要删除值对应的键)
mapData.erase(1);
? ? ? ? ④其他创建方式(有一个默认比较准则参数)
map<int,string> mapData;
map<int ,string,less<int>> mapData1; //此创建方式,等同于第一行,从小到大。
map<int,string,greater<int>>mapData2; //从大到小
? ? ? ? ⑤处理自定义数据类型:
?????????核心还是写重载函数(默认是按照键的某个属性进行比较),所以应该当键是自定义数据类型的时候,需要对键进行重载,若是用的默认的less<>比较准则,那么重载的就应该是<号
? ? ? ? (需要默认的构造函数,print()成员函数需要是const类型)
class MM
{
public:
MM() = default;
MM(string name, int age) :name(name), age(age) {}
void print() const
{
cout << name << "\t" << age << endl;
}
bool operator<(const MM& object)const
{
return this->name < object.name;
}
protected:
string name;
int age;
};
class Boy
{
public:
Boy() = default;
Boy(string name, int age) :name(name), age(age) {}
void print() const
{
cout << name << "\t" << age << endl;
}
protected:
string name;
int age;
};
void testUserData()
{
map<MM, Boy> mbData;
mbData[MM("小美", 19)] = Boy("小张", 29);
mbData[MM("小美", 19)].print();
mbData[MM("小丽", 20)] = Boy("小明", 18);
cout << "配对信息:" << endl;
for (auto v : mbData)
{
//容器管理自定义类型数据
//v:pair<MM,Boy>
//v.frist:MM
//v.second:Boy
v.first.print();
v.second.print();
}
}
?4.应用:
????????更好管理资源
?????????????????例: 在加载图片资源的时候,就直接用img[键]去对应相应的资源即可。(相比数组来说,这个下标是没有任何要求。)
#include<grapghic.h>
map<string,IMAGE*> ima;
img["墙"]=new IMAGE;
img["路"]=new IMAGE;
putimage(0,0,img["墙"]);
putimage(0,0,img["路"]);
? 五、多重映射multimap
1.特性:
????????多重映射,没有什么限制,什么样对应关系都可以插入到映射中,因为存在相同的键,所以不能采用下标法
2.基本操作
? ? ? ? 基本同单映射,除了不能用下标法。
????????????????(注:find函数找到就返回,即返回找到的第一个)
void testmultimap()
{
//多重映射,没有什么限制,什么样对应关系都可以插入到映射中
//因为存在相同的键,所以不能采用下标法
multimap<int, string> mulData;
mulData.insert(pair<int, string>(1, "string"));
mulData.insert(pair<int, string>(12, "string1"));
mulData.insert(pair<int, string>(2, "string"));
mulData.insert(pair<int, string>(3, "string"));
mulData.insert(make_pair<int, string>(3, "string"));
for (auto v : mulData)
{
cout << v.first << "\t" << v.second << endl;
}
}
输出:
1 ? ? ? string 2 ? ? ? string 3 ? ? ? string 3 ? ? ? string 12 ? ? ?string1
六、 initializer_list
头文件:#include <initializer_list>
?1.引入:
????????像这样的容器,初始化由后面的给的数据决定,构造函数的写法原理?
?2.利用:
????????initializer_list对象(迭代器)可以存储大括号内的所有数据,并且可以一一赋值给容器中,对应的位置
? ? ? ? ? ? ? ? 样例代码:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ①写一个类来简单模仿其实现的原理
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ②写一个函数来简单模仿传入多个参数的情况。
#include <array>
#include <list>
#include <vector>
#include <iostream>
#include <initializer_list>
using namespace std;
class MM
{
public:
MM(string a, string b, string c) :a(a), b(b), c(c) {}
MM(const initializer_list<string>& list)
{
for (auto iter = list.begin(); iter != list.end(); iter++)
{
cout << *iter << endl;
}
}
protected:
string a;
string b;
string c;
};
void print(initializer_list<int> list)
{
for (auto iter = list.begin(); iter != list.end(); iter++)
{
cout << *iter << " ";
}
cout << endl;
}
int main()
{
array<int, 3> arrData = { 1,2,3 };
vector<int> vecData1 = { 1,2,3,4 };
vector<int> vecData2 = { 1,2,3,4,5 };
MM mm1 = { "string1","string2","string3" };
MM mm2 = { "string1" };
MM mm3 = { "string1","string2" };
initializer_list<int> listOne = { 1,2,3,4,5 };
initializer_list<int> listTwo = { 1,2,3 };
print({ 1 });
print({ 1,2 });
print({ 1,2,3,4 });
print({ 1,2,3,4,5 });
return 0;
}
七、元组tuple容器
#include<tuple>
1.特性:
????????把任何类型的一系列数据当做一组来处理+自动增长
2.创建方式:
//方式一:
tuple<string,int,int,string> wbmInfo={"bmw",18,1001,"23123"};
//方式二:
tuple<double,double,double>wbmscore=make_tuple(99,22,33);
//方式三:
tuple<string,string>value=forward_as_tuple("阿杰","阿明");
以后结构体数组的偷懒写法:
tuple<string,int,int,string> array[3];
?3.访问数据
? ? ? ? 方式一:get方法
????????????????(不能用for循环,必须是常量)
tuple<string,int,int,string> wbmInfo={"BMW",18,1001,"2312"};
//get方法,不能用for循环
cout<<get<0>(wbmInfo)<<"\t";
cout<<get<1>(wbmInfo)<<"\t";
cout<<get<2>(wbmInfo)<<"\t";
cout<<get<3>(wbmInfo)<<"\t";
? ? ? ? 方式二:tie方法
? ? ? ? ? ? ? ? (有点类似于流操作)
tuple<string,int,int,string> wbmInfo={"BMW",18,1001,"2312"};
//tie方式访问数据
string name;
int age;
int num;
string tel;
tie(name,age,num,tel)=wbmInfo;
cout<<name<<"\t"<<age<<"\t"<<num<<"\t"<<tel<<endl;
4.其他操作:
? ? ? ? 将两个tuple连接起来: tuple_cat(参数1,参数2)
tuple<string,int,int,string> wbmInfo={"bmw",18,1001,"23123"};
tuple<double,double,double>wbmscore=make_tuple(99,22,33);
auto res=tuple_cat(wbmInfo,wbmscore);
八、了解部分(折叠参数)
//...Args代表一个参数包 //1.如何通过参数包定义变量 Args ...args? //2.如何使用参数包?? ?args... one
/*参数包的展开: ?? ?1.递归的方式,自动做一个参数包的剥离过程 ?? ?2.采用列表方式进行剥离参数*/
方式一:递归展开实现代码
#include<iostream>
using namespace std;
//递归终止函数
template <class _Ty>
void print(_Ty data)
{
cout << data<<endl;
}
template <class _Ty,class ...Args>
void print(_Ty data,Args ...args)
{
cout << data << "\t";
print(args...);//递归的方式,自身调用自身。
}
int main()
{
print(1, 2, 3, 4, "string", 12.3);
return 0;
}
?方式二:采用列表(可增长)or数组方式进行剥离参数
template <class _Ty, class ...Args>
void printdata(_Ty data)
{
cout << data << "\t";
}
template<class ...Args>
void printArgs(Args ...args)
{
//(printdata(args),0) 这是一个逗号表达式,返回的是最后一个式子的值
initializer_list<int>{(printdata(args), 0)...};
//也可以用数组做 等效于
//int array[]={(printdata(args), 0)...};
cout << endl;
}
int main()
{
printArgs(1, 2, 3, 4, "string", 12.3);
return 0;
}
printdata()是中间解析函数,负责展开打印。列表数据重复调用,(,)逗号表达式,先运行printdata再将0赋值给列表。...每次调用都会剥离分离1个出来。
|