map & set 使用快速上手【C++】

目录

一,关联式容器 

二,键值对  

三,set

1)使用参考此文档

2)count 函数

3)multiset类

四,map

1. 模板参数介绍

2.operator[]介绍

3. multimap


 英语比较好的同学可以自行查找文档 学习使用

set - C++ Reference (cplusplus.com)

一,关联式容器 

 在初阶阶段,我们已经接触过STL中的部分容器,比如:vector、list、deque、forward_list(C++11)等,这些容器统称为序列式容器,因为其底层为线性序列的数据结构,里面 存储的是元素本身。那什么是关联式容器?它与序列式容器有什么区别? 关联式容器也是用来存储数据的,与序列式容器不同的是,其里面存储的是结构的 键值对,在数据检索时比序列式容器效率更高。

序列容器和关联容器的主要区别在于元素的排列方式访问方式。序列容器按照元素的插入顺序进行排序,可以通过位置(索引)来访问元素;而关联容器按照键的顺序进行排序,可以通过键来访问元素。另外,序列容器支持快速的随机访问,而关联容器则不支持。

二,键值对  

用来表示具有一一对应关系的一种结构,该结构中一般只包含两个成员变量key和value,key代表键值,value表示与key对应的信息
比如:现在要建立一个英汉互译的字典,那该字典中必然有英文单词与其对应的中文含义,而且,英文单词与其中文含义是一一对应的关系,即通过该应该单词,在词典中就可以找到与其对应的中文含义。

像这样:

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)
  {}
};

根据应用场景的不桶,STL总共实现了 两种不同结构的管理式容器树型结构与哈希结构树型结构的关联式容器主要有四种:map、set、multimap、multiset。这四种容器的共同点是:使用平衡搜索树(即红黑树)作为其底层结果,容器中的元素是一个有序的序列。下面一依次介绍每一个容器。

三,set

特点: 

1. set是按照一定次序存储元素的容器
2. 在set中,元素的value也标识它(value就是key,类型为T),并且每个value必须是唯一的。
set中的元素不能在容器中修改(元素总是const),但是可以从容器中插入或删除它们。
3. 在内部,set中的元素总是按照其内部比较对象(类型比较)所指示的特定严格弱排序准则进行
排序。
4. set容器通过key访问单个元素的速度通常比unordered_set容器慢,但它们允许根据顺序对
子集进行直接迭代。
5. set在底层是用二叉搜索树(红黑树)实现的。
注意:
1. 与map/multimap不同,map/multimap中存储的是真正的键值对,set中只放
value,但在底层实际存放的是由构成的键值对。
2. set中插入元素时,只需要插入value即可,不需要构造键值对。
3. set中的元素不可以重复(因此可以使用set进行去重)。
4. 使用set的迭代器遍历set中的元素,可以得到有序序列
5. set中的元素默认按照小于来比较
6. set中查找某个元素,时间复杂度为:$log_2 n$
7. set中的元素不允许修改(为什么?)——保证树结构
8. set中的底层使用二叉搜索树(红黑树)来实现。

1)使用参考此文档

set - C++ Reference (cplusplus.com)

使用比较简单,就只讲解一些特殊的点:

set结构特点:

1. 中序遍历树时呈现有序性。

2. 数据去重性。

2)count 函数

set的count 函数,功能是统计相同key的个数。

功能意义不是很大,因为set类具有去重性,所以就跟find()函数功能重合。

3)multiset类

multiset类与set一个重要区别——multiset类允许重复数据

假设:2 2 3,插入2,2的位置可以是2的左右孩子; 当通过查找时(set一般通过中序查找方法)首先查到的2也就是中序最先遍历到的。

四,map

1. map是关联容器,它按照特定的次序(按照key来比较)存储由键值key和值value组合而成的元素。
2. 在map中,键值key通常用于排序和惟一地标识元素,而值value中存储与此键值key关联的内容。键值key和值value的类型可能不同,并且在map的内部,key与value通过成员类型 value_type绑定在一起,为其取别名称为pair:  typedef pair value_type;
3. 在内部,map中的元素总是按照键值 key进行比较排序的
4. map中通过键值访问单个元素的速度通常比unordered_map容器慢,但map允许根据顺序对元素进行直接迭代(即对map中的元素进行迭代时,可以得到一个有序的序列)。
5. map支持下标访问符,即在[]中放入key,就可以找到与key对应的value。
6. map通常被实现为二叉搜索树(更准确的说:平衡二叉搜索树(红黑树))。

1. 模板参数介绍

map & set 使用快速上手【C++】_第1张图片

key: 键值对中key的类型
T: 键值对中value的类型
Compare: 比较器的类型,map中的元素是按照key来比较的,缺省情况下按照小于来比较,一般情况下(内置类型元素)该参数不需要传递,如果无法比较时(自定义类型),需要用户自己显式传递比较规则(一般情况下按照函数指针或者仿函数来传递)
Alloc:通过空间配置器来申请底层空间,不需要用户传递,除非用户不想使用标准库提供的空间配置器。
简单尝试一下下面代码:
void Test_map()
{
	map m1;
	m1.insert(make_pair("string", "字符串")); // 可以写成pair("string", "字符串"),创建匿名对象
	m1.insert(make_pair("func", "函数"));
	m1.insert(make_pair("sort", "排序"));
	m1.insert(make_pair("void", "空返回"));

	auto dir = m1.begin();
	while (dir != m1.end())
	{
		cout << (*dir).first << " second:" << (*dir).second << endl;
        // cout<< dir->first ... ,dir是迭代器类型,STL一般是实现了->的重载
		dir++;
	}
	cout << endl;
}

以上代码中使用了make_pair类,那这个make_pair类有什么特点??

本质上就是一个模板函数,里面封装了返回匿名对象,选择使用这么模板函数目的就是省略pair类型的填写,类型自动推导。

map & set 使用快速上手【C++】_第2张图片

2.operator[]介绍

可以简单理解为:通过该成员函数,返回键值表中的_val的引用。(不理解也没关系,后面逐步理解) 

我们先尝试写一个记录物品数量的代码
void Test_map_operator()
{
	const char* arr[] = { "瓜", "花","瓜", "梨", "瓜" };

	map count;
	for (auto& e : arr)
	{
		auto ret = count.find(e);
		if ( ret == count.end())
		{
			count.insert(make_pair(e, 1));
		}
		else
		{
			ret->second++;
		}
		// count[e]++;
	}
	for (auto& e : count)
	{
		cout << e.first << ":" << e.second << endl;
	}
}

结果是正常的,然后我们将第一个auto的函数内容注释,替代为cout[e]++;  运行。运行结果跟我们的代码结果相同。这就有意思了。

文档中是这样解释这个代码的等效代码:

我们分析一下:
map & set 使用快速上手【C++】_第3张图片
简单来个实验:
void Test_map_insert()
{
	map m1;
	m1.insert(make_pair("string", "字符串"));
	m1.insert(make_pair("func", "函数"));
	m1.insert(make_pair("sort", "排序"));
	m1.insert(make_pair("void", "空返回"));

	m1["afeng"];            // 查找,如果没有,则进行创建(修改)
	m1["afeng"] = "阿峰";   // 修改
	cout << m1["afeng"] << endl;
	m1["afeng"] = "阿峰fc"; // 查找 + 修改
	cout << m1["afeng"] << endl;
}

3. multimap

multimap中的接口可以参考map,功能都是类似的。
注意:
1. multimap中的key是可以重复的。
2. multimap中的元素默认将key按照小于来比较
3. multimap中没有重载operator[]操作(同学们可思考下为什么?)。(因为允许键值冗余,所以无法准确查找到对应的键值对)
4. 使用时与map包含的头文件相同

下一期预告:我们从底层了解AVL树,上强度!

结语

   本小节就到这里了,感谢小伙伴的浏览,如果有什么建议,欢迎在评论区评论,如果给小伙伴带来一些收获请留下你的小赞,你的点赞和关注将会成为博主创作的动力

你可能感兴趣的:(C++——从入门到入土,安排!,c++,开发语言,算法)