一:序列式容器和关联式容器
二:set系列的使⽤
三:map系列的使⽤
一:序列式容器和关联式容器
前⾯我们已经接触过STL中的部分容器如:string、vector、list、deque、array、forward_list等,这些容器统称为序列式容器,因为逻辑结构为线性序列的数据结构,两个位置存储的值之间⼀般没有紧密的关联关系,⽐如交换⼀下,他依旧是序列式容器。顺序容器中的元素是按他们在容器中的存储位置来顺序保存和访问的。
关联式容器也是⽤来存储数据的,与序列式容器不同的是,关联式容器逻辑结构通常是⾮线性结构,两个位置有紧密的关联关系,交换⼀下,他的存储结构就被破坏了。顺序容器中的元素是按关键字来保存和访问的。关联式容器有map/set系列和unordered_map/unordered_set系列。
本章节讲解的map和set底层是红⿊树,红⿊树是⼀颗平衡⼆叉搜索树。set是key搜索场景的结构,map是key/value搜索场景的结构。
二:set系列的使⽤
2.1介绍set
下面我截的图不太清晰,大家可以上这个链接set - C++ Reference,看看有关set的介绍
set的声明如下,T就是set底层关键字的类型
• set默认要求T⽀持⼩于⽐较,如果不⽀持或者想按⾃⼰的需求⾛可以⾃⾏实现仿函数传给第⼆个模版参数
• set底层存储数据的内存是从空间配置器申请的,如果需要可以⾃⼰实现内存池,传给第三个参数。
• ⼀般情况下,我们都不需要传后两个模版参数。
• set底层是⽤红⿊树实现,增删查效率是log N
,迭代器遍历是⾛的搜索树的中序,所以是有序
的。
O(logN)
• 前⾯部分我们已经学习了vector/list等容器的使⽤,STL容器接⼝设计,⾼度相似,所以这⾥我们就不再⼀个接⼝⼀个接⼝的介绍,⽽是直接带着⼤家看⽂档,挑⽐较重要的接⼝进⾏介绍。

set
set是容器它是按照特定的顺序存储唯一的元素
在set,元素的值也可以标识它自己(值本身就是类型为 T 的键),值必须是唯一的,值不能修改在容器中,但可以从容器中插入或删除元素。
在内部,集合中的元素总是按照其内部比较对象(类型为 Compare)所指定的特定严格弱序准则进行排序。
通常情况下,通过键来访问集合(set)容器中的单个元素比访问无序集合(unordered_set)容器中的元素要慢,但集合允许基于元素顺序直接对子集进行迭代操作。
集合通常是通过二叉搜索树来实现的。
2.2
set的构造和迭代器
set的构造分为以下四类

// initializer list (5) initializer 列表构造
set (initializer_list<value_type> il,
const key_compare& comp = key_compare(),const allocator_type& alloc = allocator_type());
set的迭代器
先看迭代器有哪些







2.3
set的增删查改
1: set去重和升序排序

2.插入数据,已存在的数据插入失败

3.遍历string⽐较ascll码⼤⼩顺序遍历的
ascll码⼤⼩顺序遍历的是啥意思,它是通过比较ascll码大小,由小到大顺序排列

4.删除值
4.1
删除最小值
set会对这串数据进行升序,而我要删除的是首元素,即是数据中最小的值

4.2
随意删除
思路是:输入任意值,然后如果值在数据串,就删除了,否则没有删除成功

5.查找元素
查找元素,有两种查找方式
一是:算法库的查找 O(N)
二是:set⾃⾝实现的查找 O(logN)

5.2
利⽤count间接实现快速查找

5.3
删除数据区间



三:map的使用
3.1介绍map

Key:是map底层关键字的类型
T:是map底层val的类型
set默认要求Key⽀持⼩于⽐较,如果不⽀持或者需要的话可以⾃⾏实现仿函数传给第⼆个模版参数,map底层存储数据的内存是从空间配置器申请的。
map底层是⽤红⿊树实现,增删查改效率是O(log N),迭代器遍历是⾛的中序,所以是按key有序顺序遍历的。
3.2
pair类型的介绍
map底层的红⿊树节点中的数据,使⽤pair<Key,T>存储键值对数据。
typedef pair<const Key, T> value_type;
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)
{}
template<class U, class V>
//模板构造函数
pair (const pair<U,V>& pr): first(pr.first), second(pr.second)
{}
};
template <class T1,class T2>inline pair<T1,T2> make_pair (T1 x, T2 y)
{
return ( pair<T1,T2>(x,y) );
}


3.3map的构造
一:默认构造函数
此构造函数会创建一个空的 map。
#include <iostream>
#include <map>
int main() {
std::map<int, std::string> myMap;
std::cout << "Size of myMap: " << myMap.size() << std::endl;
return 0;
}
二:范围构造函数
该构造函数使用来自另一个范围(如另一个 map 或 std::pair 的序列)的元素来初始化 map。
int main()
{
vector<pair<int, string>> vec = { {1,"cic"},{2,"cia"},{4,"yus"} };
map<int, string> mysu(vec.begin(), vec.end());
for (const auto& pair : mysu)
{
cout << pair.first << " : " << pair.second << endl;
}
return 0;
}
三:拷贝构造函数
这个构造函数用另一个 map 的副本初始化新的 map

四:初始化列表构造函数
该构造函数使用初始化列表来初始化 map

五.map的增删查改
int main()
{
map<string, string> dict = { {"left", "左边"}, {"right", "右边"},{"insert", "插⼊"},{ "string", "字符串" } };
//map<string, string>::iterator it = dict.begin();
auto it = dict.begin();
map<string, string>::iterator it1;
while (it != dict.end())
{
cout << it->first << ":" << it->second << endl;
++it;
}
cout << endl;
//insert插入pair对象的4种方式,对比之下,最后一个最方便
/*创建了一个 std::pair 对象 kv1,它包含两个 std::string 类型的元素,第一个元素 "first" 作为键,第二个元素 "第⼀个" 作为值。*/
pair<string, string> kv2("first", "第一个");
//insert插入pair对象的4种方式,对比之下,最后一个最方便
dict.insert(kv2);
dict.insert(pair<string, string>("second", "第⼆个"));
dict.insert(make_pair("sort", "排序"));
dict.insert({ "auto", "⾃动的" });
//查找数据
it1 = dict.find(kv2.first);
while (it1 != dict.end())
{
//删除数据
dict.erase(it1);
}
// 范围for遍历
for (const auto& e : dict)
{
cout << e.first << ":" << e.second << endl;
}
cout << endl;
/*string str;
while (cin >> str)
{
auto ret = dict.find(str);
if (ret != dict.end())
{
cout << "->" << ret->second << endl;
}
else
{
cout << "⽆此单词,请重新输⼊" << endl;
}
}*/
return 0;
//
2094

被折叠的 条评论
为什么被折叠?



