C++中STL---map
1、前言
在C++中,我们之前所学习的string、vector、list 、数组等这些容器都是统称为序列式容器。今天所学习的【map】为关联式容器,通常用于存储被经常检索的数据;不同于其他STL容器,它的查找速度极快,时间复杂度为O(1),底层用红黑树封装。
2、预备知识
2.1 序列式容器
string、vector、list 、数组等序列式容器的特点就是 底层为线性序列的数据结构,就比如list
,其中的节点是线性存储的,两个位置存储的值之间⼀般没有紧密的关联关系,比如交换一下,它依旧是序列式容器。顺序容器中的元素是按他们在容器中的存储位置来顺序保存和访问的。
2.2 关联式容器
2.3 键值对
键值对是一种用来表示一一对应关系的结构,该结构一般有两个成员变量key和value,key表示键值,value表示实值。对于一一对应的关系,也可以称之为映射关系:存储的数据都是成对存在的,破坏了对应关系,数据丢失了。
在对于键值对存储数据,标准库中提供了pair结构。
template <class T1, class T2>
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) {}#ifdef __STL_MEMBER_TEMPLATEStemplate <class U1, class U2>pair(const pair<U1, U2>& p) : first(p.first), second(p.second) {}
#endif
};
3. set系列的使用
3.1 什么是set?
set 集合是一种关联容器,用于存储唯一的元素,并且这些元素会按照特定的顺序自动排序,默认是升序排列。这就好比一个智能书架,每本书都是独一无二的,并且书架会自动按照书名的字母顺序排列书籍,方便查找。例如,存储整数的 set
中不会有重复的整数,插入元素时,set
会自动调整元素位置以保证排序。
3.2 set结构
class T:使用类模板,表示存储在set中的数据类型。
class Compare = less<T>:这是用于定义元素比较规则的模板参数,默认规则是进行小于(<)比较。
class Alloc = allocator<T>:内存分配器相关的模板参数,内存分配器负责在
set
需要分配和释放内存时管理内存的分配和回收。allocator<T>
是标准库提供的默认内存分配器,它提供了基本的内存分配和释放功能。但在一些特殊场景下,比如需要自定义内存管理策略(例如,使用特定的内存池)时,可以自定义内存分配器类并将其作为该参数传入。
3.3 set的构造和迭代器
// empty (1) ⽆参默认构造
explicit set(const key_compare& comp = key_compare(),const allocator_type& alloc = allocator_type());
// range (2) 迭代器区间构造
template <class InputIterator>
set(InputIterator first, InputIterator last,const key_compare& comp = key_compare(),const allocator_type & = allocator_type());
// copy (3) 拷⻉构造
set(const set& x);
迭代器:
// 正向迭代器
iterator begin();
iterator end();
// 反向迭代器
reverse_iterator rbegin();
reverse_iterator rend();
3.3 set定义
set<类型名> 变量名;
其中类型名可以是任意模版:
set<int> i;
set<char> c;
set<vector> v;
set<struct node> n;
3.4 迭代器遍历
set容器内的元素访问:我们只能使用迭代器(iterator)进行数据的访问:
#include <iostream>
#include <set>using namespace std;int main()
{// 默认升序+去重set<int> s;s.insert(1);s.insert(2);s.insert(3);s.insert(1);auto it = s.begin();while (it != s.end()){cout << *it << " ";it++;}cout << endl;// 插⼊⼀段initializer_list列表值s.insert({ 2,8,3,9 });for (auto e : s){cout << e << " ";}cout << endl;set<string> strset = { "sort", "insert", "add" };// 遍历string⽐较ascll码⼤⼩顺序遍历的for (auto& e : strset){cout << e << " ";}cout << endl;return 0;
}
也支持特定位置的插入:
#include <iostream>
#include <set>using namespace std;int main()
{set<int> s;s.insert(1);s.insert(2);s.insert(3);s.insert(1);auto it = s.find(3);s.insert(it, 4);for (int num : s){std::cout << num << " ";}cout << endl;return 0;
}
3.5 set容器中常用的函数
find():find(value) 返回 set 中 value 所对应的迭代器,即 value 的指针(地址),如果没找到则返回 end()。
#include <iostream>
#include <set>using namespace std;int main()
{int x;set<int> s;for (int i = 1; i <= 3; i++){s.insert(i);}cin >> x;auto it = s.find(x);if (it != s.end()){cout << "----" << endl;}cout << endl;return 0;
}
erase():可以删除单个元素或删除一个区间内的所有元素
#include <iostream>
#include <set>using namespace std;int main()
{set<int> s;s.insert(1);s.insert(2);s.insert(3);s.insert(3);s.insert(5);// 删除一个元素s.erase(s.find(1)); // 删除一个区间内的所有元素s.erase(s.begin(), s.end());for (auto it = s.begin(); it != s.end(); it++){cout << *it << " ";}return 0;
}
lower_bound:表示该函数用于查找容器中某个特定元素的下界。
#include <iostream>
#include <set>using namespace std;
int main()
{std::set<int> myset;for (int i = 1; i < 10; i++)myset.insert(i * 10); // 10 20 30 40 50 60 70 80 90for (auto e : myset){cout << e << " ";}cout << endl;// 实现查找到的[itlow,itup)包含[30, 60]区间// 返回 >= 30auto itlow = myset.lower_bound(30);// 返回 > 60auto itup = myset.upper_bound(60);// 删除这段区间的值myset.erase(itlow, itup);for (auto e : myset){cout << e << " ";}cout << endl;return 0;
}
begin(); // 返回指向第一个元素的迭代器
end(); // 返回指向最后一个元素的后一个位置的迭代器
clear(); // 清除所有元素
count(); // 返回某个值元素的个数,用于判断set中是否有该元素
size(); // 返回集合中元素的数目
empty(); // 如果集合为空,返回true,否则返回false
equal_range(); // 返回集合中与给定值相等的上下限的两个迭代器
insert(); // 在集合中插入元素
erase(); // 删除集合中的元素
find(); // 返回一个指向被查找到元素的迭代器
get_allocator(); // 返回集合的分配器
upper_bound(); // 返回大于某个值元素的迭代器
lower_bound(); // 返回指向大于(或等于)某值的第一个元素的迭代器
key_comp(); // 返回一个用于元素键值比较的函数
value_comp(); // 返回一个用于比较元素间的值的函数
max_size(); // 返回集合能容纳的元素的最大限值
rbegin(); // 返回set反转后的开始指针(即原来的end-1)
rend(); // 返回set反转后的结束指针(即原来的begin-1)
swap(); // 交换两个集合变量
4. multiset与set的区别
multiset 和 set 的使用基本完全类似,主要区别点在于multiset支持值冗余,也就是不去重,不唯一。
#include <iostream>
#include <set>using namespace std;
int main()
{// 相⽐set不同的是,multiset是排序,但是不去重multiset<int> s = { 4,2,7,2,4,8,4,5,4,9 };auto it = s.begin();while (it != s.end()){cout << *it << " ";++it;}cout << endl;// 相⽐set不同的是,x可能会存在多个,find查找中序的第⼀个int x;cin >> x;auto pos = s.find(x);while (pos != s.end() && *pos == x){cout << *pos << " ";++pos;}cout << endl;// 相⽐set不同的是,count会返回x的实际个数cout << s.count(x) << endl;// 相⽐set不同的是,erase给值时会删除所有的xs.erase(x);for (auto e : s){cout << e << " ";}cout << endl;return 0;
}
请不要叫我宅男,请叫我闭家锁;请不要叫我宅女,请叫我居里夫人,完结!!!