前面了解过的vector,list,string等容器都是序列式容器,存储的都是元素本身,底层都是线性的数据结构。
而map和set存储的都是
STL中对键值对的定义:
template
struct pair
{
typedef T1 first_type;
typedef T2 second_type;
T1 first;
T2 second;
pair(): first(T1()), second(T2())
{}
pair(const T1& a, const T2& b): first(a), second(b)
{}
};
文档:https://legacy.cplusplus.com/reference/set/set/?kw=set
void test_set1()
{
// 排序+去重
set<int> s;
s.insert(3);
s.insert(3);
s.insert(3);
s.insert(5);
s.insert(8);
s.insert(7);
for (auto e : s)
{
cout << e << " ";
}
cout << endl;//3 5 7 8
if (s.find(5) != s.end())
{
cout << "找到了" << endl;
}
if (s.count(5))
{
cout << "找到了" << endl;
}
std::set<int> myset;
std::set<int>::iterator itlow, itup;
for (int i = 1; i < 10; i++)
myset.insert(i * 10); // 10 20 30 40 50 60 70 80 90
myset.insert(35);
// 删除[30 60]
//itlow = myset.lower_bound(30); // >=
//itup = myset.upper_bound(60); // >
//std::pair::const_iterator, std::set::const_iterator> ret;
auto ret = myset.equal_range(30);//ret的类型是pair
itlow = ret.first;
itup = ret.second;
// [itlow, itup)
cout << *itlow << endl;
cout << *itup << endl;
myset.erase(itlow, itup);
for (auto e : myset)
{
cout << e << " ";
}
cout << endl; // 10 20 70 80 90
}
void test_set2()
{
// 排序
multiset<int> s;
s.insert(3);
s.insert(5);
s.insert(8);
s.insert(7);
s.insert(7);
s.insert(9);
s.insert(7);
for (auto e : s)
{
cout << e << " ";//3 5 7 7 7 8 9
}
cout << endl;
// 返回中序第一个7
auto pos = s.find(7);
while (pos != s.end())
{
cout << *pos << " "; //7 7 7 8 9
++pos;
}
cout << endl;
cout << s.count(7) << endl; //3
}
和set的相同点:
默认按照小于的方式对key进行比较
map中的元素如果用迭代器去遍历,可以得到一个有序的序列
map的底层为平衡搜索树(红黑树),查找效率比较高 O ( l o g 2 N ) O(log_2 N) O(log2N)
不同点
C++11支持多参数的构造函数隐式类型的转换,但是C++98没有
// 隐式类型的转换
class A
{
public:
A(int a1, int a2)
:_a1(a1)
, _a2(a2)
{}
private:
int _a1;
int _a2;
};
string str1 = "hello";
A aa1 = { 1, 2 };
pair<string, string> kv2 = { "string", "字符串" };
多种形式
void test_map1()
{
map<string, string> dict;
pair<string, string> kv1("insert", "插入");
dict.insert(kv1);
dict.insert(pair<string, string>("sort", "排序"));
// C++98
dict.insert(make_pair("string", "字符串"));
// C++11 多参数的构造函数隐式类型转换
dict.insert({ "string", "字符串" });
// 隐式类型的转换
string str1 = "hello";
A aa1 = { 1, 2 };
pair<string, string> kv2 = { "string", "字符串" };
}
] 插入时若map中已经有key,不对value进行覆盖
void test_map2()
{
map<string, string> dict;
dict.insert(make_pair("string", "字符串"));
dict.insert(make_pair("sort", "排序"));
dict.insert(make_pair("insert", "插入"));
// 不插入,不覆盖;插入过程中,只比较key,value是相同无所谓
// key已经有了就不插入了
dict.insert(make_pair("insert", "xxxx"));
auto it = dict.begin();
while (it != dict.end())
{
//cout << (*it).first << ":" << (*it).second << endl;
cout << it->first << ":" << it->second << endl;
++it;
}
cout << endl;
for (const auto& kv : dict)
{
cout << kv.first << ":" << kv.second << endl;
}
}
operator[],若map中没有该元素,则会先进行插入
void test_map4()
{
map<string, string> dict;
dict.insert(make_pair("string", "字符串"));
dict.insert(make_pair("sort", "排序"));
dict.insert(make_pair("insert", "插入"));
cout << dict["sort"] << endl; // 查找和读
dict["map"]; // 插入
dict["map"] = "映射,地图"; // 修改
dict["insert"] = "xxx"; // 修改
dict["set"] = "集合"; // 插入+修改
}