STL之三:关联容器
一、关联容器概述
关联容器通过 键(Key) 高效存储和访问元素,它们的元素位置取决于键值,而非插入顺序。主要分为两类:
1.无序关联容器,依赖于链式哈希表,增删查O(1)
使用头文件:#include<unordered_set>、#include<unordered_map>
set:集合 key map:映射表[key, value](键值对)
unordered_set:单重集合
unordered_multiset:多重集合
unordered_map:单重映射表
unordered_multimap:多重映射表
2.有序关联容器,依赖于红黑树,增删查O(log2n),2是底数(树的层数,树的高度)
使用头文件:#include<set>、#include<map>
set
multiset
map
multimap
map 和 set:每个关键字(Key)必须是唯一的。如果插入重复的关键字,操作会被忽略(不会报错)。
#include<iostream>
#include<set>
#include<map>
#include<unordered_set>
#include<unordered_map>
using namespace std;
int main()
{
unordered_set<int> set1; //不会存储key值重复的元素
for (int i = 0; i < 50; i++)
{
set1.insert(rand() % 20 + 1);
}
cout << set1.size() << endl;
cout << set1.count(15) << endl;
return 0;
}
得到的输出是18和1,说明有很多元素是重复的,15只出现1次。
multiset 和 multimap:允许重复的关键字。插入操作始终成功,不检查重复性。
#include<iostream>
#include<set>
#include<map>
#include<unordered_set>
#include<unordered_map>
using namespace std;
int main()
{
unordered_multiset<int> set1; //改为多重集合
for (int i = 0; i < 50; i++)
{
set1.insert(rand() % 20 + 1);
}
cout << set1.size() << endl;
cout << set1.count(15) << endl;
return 0;
}
得到的输出是50和2,说明重复的元素也可以存储。
二、无序关联容器
1.无序set
各个容器底层的数据结构 O(1) O(log2n)
增加:insert(val)
遍历:iterator自己搜索,调用find成员方法
删除:erase(key)、erase(it)
#include<iostream>
#include<set>
#include<map>
#include<unordered_set>
#include<unordered_map>
using namespace std;
int main()
{
unordered_set<int> set1; //不会存储key值重复的元素
for (int i = 0; i < 50; i++)
{
set1.insert(rand() % 20 + 1);
}
auto it1 = set1.begin();
for (; it1 != set1.end(); ++it1)
{
cout << *it1 << " ";
}
cout << endl;
set1.erase(20); //按key值删除元素
for (it1 != set1.begin(); it1 != set1.end(); ++it1)
{
if (*it1 != 30)
{
it1 = set1.erase(it1); //调用erase,it1迭代器就失效了
}
else
{
++it1;
}
}
it1 = set1.find(20);
if (it1 != set1.end())
{
set1.erase(it1);
}
for (int v : set1)
{
cout << v << " ";
}
return 0;
}
2.无序map
map的operator[ ]
1)查询
2)如果key不存在,它会插入一对数据[key, string( )]因为:
[key, value]struct pair
{
first: =>key
second: =>value
}
所以,访问迭代器时可以用first和second访问键值对
int main()
{
unordered_map<int, string>map1;
map1.insert(make_pair(1000, "张三"));
map1.insert({ 1010,"李四" });
map1.insert({ 1020,"王五" });
map1.insert({ 1030,"王凯" });
map1.erase(1020);
map1[2000];
cout << map1.size() << endl;
//map operator[](key) => value 查询
cout << map1[1000] << endl;
return 0;
}
输出结果,size得到4,但实际只有3,说明使用map的operator[ ]时,当kye不存在,就会插入一对数据。
#include<iostream>
#include<set>
#include<map>
#include<unordered_set>
#include<unordered_map>
#include<string>
using namespace std;
int main()
{
unordered_map<int, string>map1;
map1.insert(make_pair(1000, "张三"));
map1.insert({ 1010,"李四" });
map1.insert({ 1020,"王五" });
map1.insert({ 1030,"王凯" });
map1.erase(1020);
auto it1 = map1.find(1030);
if (it1 != map1.end())
{
cout << "key:" << it1->first << " value:" << it1->second << endl;
}
//map1[2000];
map1[2000] = "刘说"; //根据key对其value进行插入操作
map1[1000] = "张三2"; //根据key对其value进行修改操作
cout << map1.size() << endl;
//map operator[](key) => value 查询
cout << map1[1000] << endl;
return 0;
}
3.什么时候使用哈希表?
①处理海量数据查重复
int main()
{
const int ARR_LEN = 100;
int arr[ARR_LEN] = { 0 };
for (int i = 0; i < ARR_LEN; ++i)
{
arr[i] = rand() % 20 + 1;
}
// 上面的100个整数中,统计哪些数字重复了,并且统计数字重复的次数
unordered_map<int, int>map1;
for (int k : arr)
{
auto it = map1.find(k);
if (it == map1.end())
{
map1.insert({ k,1 });
}
else
{
it->second++;
}
}
for (pair<int, int>p : map1)
{
if (p.second > 1)
{
cout << "key:" << p.first << " count:" << p.second << endl;
}
}
cout << endl;
auto it = map1.begin();
for (; it != map1.end();++it)
{
if (it->second > 1)
{
cout << "key:" << it->first << " count:" << it->second << endl;
}
}
return 0;
}
②去重复的时候
int main()
{
const int ARR_LEN = 100;
int arr[ARR_LEN] = { 0 };
for (int i = 0; i < ARR_LEN; ++i)
{
arr[i] = rand() % 20 + 1;
}
//上面的100个整数中,把数字进行去重打印
unordered_set<int> set;
for (int v : arr)
{
set.insert(v);
}
for (int v : set)
{
cout << v << " ";
}
cout << endl;
return 0;
}
三、有序关联容器
输出是有序的!!!
1.有序set
int main()
{
set<int> set1;
for (int i = 0; i < 20; ++i)
{
set1.insert(rand() % 20 + 1);
}
for (int v : set1)
{
cout << v << " ";
} //输出1 2 3 5 6 8 10 12 15 16 17 19,是有序的
return 0;
}
#include<iostream>
#include<set>
#include<map>
#include<unordered_set>
#include<unordered_map>
#include<string>
using namespace std;
class Student
{
public:
Student(int id,string name):_id(id),_name(name) { }
bool operator<(const Student& stu)const
{
return _id < stu. _id;
}
private:
int _id;
string _name;
friend ostream& operator<<(ostream& out, const Student& stu);
};
ostream& operator<<(ostream& out, const Student& stu)
{
out << "id:" << stu._id << " name:" << stu._name << endl;
return out;
}
int main()
{
set< Student> set1;
set1.insert(Student(1000, "张问"));
set1.insert(Student(1020, "李广"));
for (auto it = set1.begin(); it != set1.end(); ++it)
{
cout << *it << endl;
}
return 0;
}
2.有序map
//对上面代码做出部分修改,其余地方保持不变
int main()
{
map<int, Student>stumap;
stumap.insert({ 1000,Student(1000,"张问") });
stumap.insert({ 1020,Student(1020,"李三") });
stumap.insert({ 1030,Student(1030,"高阳") });
// stumap.erase(it) stumap.erase(1020)
//cout << stumap[1020] << endl;
for (auto it = stumap.begin(); it != stumap.end(); ++it)
{
cout << "key:" << it->first << " value:" << it->second << endl;
}
cout << endl;
return 0;
}
更多推荐

所有评论(0)