关联式容器存储元素,往往就是看中了关联式容器可以快速查找、读取或者删除所存储的元素,同时该类型容器插入元素的效率也比序列式容器高。
一、set容器
1. 特点
- 不再以键值对的方式存储数据,因为 set 容器专门用于存储键和值相等的键值对,因此该容器中真正存储的是各个键值对的值(value)
- set 容器在存储数据时,会根据各元素值的大小对存储的元素进行排序(默认做升序排序)
- 存储到 set 容器中的元素,虽然其类型没有明确用 const 修饰,但正常情况下它们的值是无法被修改的(只能用erase、clear修改)
- set 容器存储的元素必须互不相等
2. 使用
set容器的类模板为:
template < class T, // 键 key 和值 value 的类型
class Compare = less<T>, // 指定 set 容器内部的排序规则
class Alloc = allocator<T> // 指定分配器对象的类型
> class set;
一般我们只设置第一个参数(存储数据类型的参数)和第二个参数(排序原则),排序原则可以根据需求自定义,默认值为 less<T>
即小的排前面。
set容器的功能函数可以参考 REFERENCE,下面举例使用set
#include <iostream>
#include <set>
using namespace std;
struct mycmp{
bool operator() (int a, int b){
return a > b;
}
};
int main()
{
set<int, mycmp> myset; // custom order
set<int, std::greater<int>> s; // greater first
s.insert(5);
s.insert(2);
s.insert(3);
s.insert(1);
s.insert(2);
s.insert(6); // repeat
// size()
cout << "size = " << s.size() << endl;
// erase()
s.erase(6);
// find()
auto it = s.find(2);
if (it != s.end()){
cout << "Successfully!" << endl;
}
// empty()
if (s.empty()){
cout << "The set is empty now." << endl;
}
// traverse
for (auto elem : s){
cout << elem << " ";
}
cout << endl;
// count()
cout << "\nElement" << "\t" << "Count" << endl;
for (set<int>::iterator it=s.begin(); it!=s.end(); it++){
cout << *it << "\t" << s.count(*it) << endl;
}
return 0;
}
输出结果为:
size = 5
Successfully!
5 3 2 1
Element Count
5 1
3 1
2 1
1 1
其中,结构体 mycmp
的作用是 自定义排序 规则,作为set<>内的参数。mycmp结构体/类的定义方法如下,包含了一个运算符重载,建议使用常引用)
struct mycmp{ // 大的排前面(降序)
bool operator() (const int &a, const int &b){
return a > b;
}
};
set<int, mycmp> myset; // custom order
set<int, std::greater<int>> s; // greater first
对于 自定义的数据类型 ,可以这样子重载运算符:
#include <iostream>
#include <set>
#include <string>
using namespace std;
class Student{
public:
string name;
int number;
int score;
Student(string na, int nu, int sc):name(na), number(nu), score(sc){}
};
struct mycmp{
bool operator() (const Student &stud1, const Student &stud2){
return stud1.score < stud2.score;
}
};
int main()
{
set<Student> s;
Student stud1("Lucy", 1, 86);
Student stud2("Tom", 2, 95);
s.insert(stud1);
s.insert(stud2);
return 0;
}
若无 mycmp
结构体,则会报错:
In instantiation of ‘bool std::less<_Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp = Student]’:
二、multiset容器
1. 特点
multiset 容器和 set 容器唯一的差别在于,multiset 容器允许存储多个值相同的元素,而 set 容器中只能存储互不相同的元素。
2. 使用
#include <iostream>
#include <set>
using namespace std;
int main()
{
multiset<int> mymultiset{1, 2, 4, 3, 2, 6};
mymultiset.insert(5);
mymultiset.erase(6);
// size()
cout << "size: " << mymultiset.size() << endl;
// traverse
cout << endl << "traverse: " << endl;
for (auto elem : mymultiset){
cout << elem << " ";
}
// find()
cout << "\n\nfind(3)..." << endl;
if (mymultiset.find(3) != mymultiset.end()){
cout << "successfully!" << endl;
cout << "The next element is " << *(mymultiset.find(3)++) << endl;
}
// count()
cout << "\nelement" << "\t" << "count" << endl;
for (auto it=mymultiset.begin(); it!=mymultiset.end(); it++){
cout << *it << "\t" << mymultiset.count(*it) << endl;
}
return 0;
}
结果如下:
size: 6
traverse:
1 2 2 3 4 5
find(3)...
successfully!
The next element is 3
element count
1 1
2 2
2 2
3 1
4 1
5 1
--------------------------------
Process exited after 2.543 seconds with return value 0
请按任意键继续. . .
三、map容器
1. 特点
- 存储
key-value
键值对 - 按
key
进行排序,key
不允许重复也不能修改 - 可以通过迭代器访问key-value:
it->first
,(*it).second
2. 使用
map的 模板 为:
template < class Key, // 指定键(key)的类型
class T, // 指定值(value)的类型
class Compare = less<Key>, // 指定排序规则
class Alloc = allocator<pair<const Key,T> > // 指定分配器对象的类型
> class map;
map 容器模板有 4 个参数,其中后 2 个参数都设有默认值。大多数场景中,我们只需要设定前 2 个参数的值,有些场景可能会用到第 3 个参数,但最后一个参数几乎不会用到。
下面举例说明定义map、插入键值对、删除键值对、查找、访问等:
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main()
{
map<int, string> m;
map<int, string, std::less<int>> m1; // less order
map<string, string, greater<string>> m2; // greater order
m[2] = "banana"; // add items
m.insert(pair<int, string>(1, "apple"));
m.insert(make_pair(3, "peach"));
// traverse
for (auto elem : m){
cout << elem.first << " " << elem.second << endl;
}
cout << endl;
m[2] = "happy";
// reverse traverse
map<int, string>::reverse_iterator rit;
for (rit=m.rbegin(); rit!=m.rend(); rit++){
cout << rit->first << " " << (*rit).second << endl;
}
// find(key)
auto it = m.find(2); // return a iterator
if (it != m.end()){
cout << "\nThe element with the key 2 is: " << it->second << endl;
}
cout << m[1] << endl;
cout << m.at(3) << endl; // at(key)
if (!m.empty()){
cout << "Size: " << m.size() << endl;
}
return 0;
}
输出结果为:
1 apple
2 banana
3 peach
3 peach
2 happy
1 apple
The element with the key 2 is: happy
apple
peach
Size: 3
--------------------------------
Process exited after 3.04 seconds with return value 0
请按任意键继续. . .
四、multimap容器
和 map 容器的区别在于,multimap 容器中可以同时存储多(≥2)个键相同的键值对。
参考内容:REFERENCE