STL源码——关联式容器及其底层红黑树实现(上) 之 关联式容器详细介绍

2023-11-07

在侯捷老师源码剖析一书中对关联式进行源码剖析前先花了不少篇幅介绍红黑树的原理,这是因为关联式容器的底层依赖于RB_Tree实现。
因此想尝试在下篇剖析红黑树的源码,在此之前,先复习一下各个关联式容器的方法及容器之间的不同之处或许对红黑树的剖析会有“带着问题看文章”的感觉。


map/multimap

map和multimap都需要#include<map>, 唯一不同就是map的键值key不可以重复,但是multimap可以,也因此map可以用[]运算符,而multimap不支持

map提供一对一的数据处理能力,map内部自建一棵红黑树(红黑树不是一种严格意义上的平衡二叉树),红黑树对数据有自动排序的功能,所以在map内部的数据都是有序的

map/multimap的基本操作函数

begin() 返回指向头部的迭代器
clear() 删除所有元素
count() 返回指定元素出现的次数
empty() 是否为空,空则返回1
end() 返回指向尾部的迭代器
equal_range()返回特殊条目的迭代器对
erase() 删除一个元素
find() 查找一个元素
get_allocator() 返回配置器
insert() 插入元素
key_comp() 返回比较元素key的函数
value_comp() 返回比较元素value的函数
lower_bound() 返回键值 >= 给定元素的第一个位置 第一个小于或等于
upper_bound() 返回键值 > 给定元素的第一个位置 第一个小于
rbegin() 返回指向尾部的逆向迭代器
rend() 返回指向头部的逆向迭代器
size() 返回map中元素的个数
max_size() 返回可以容纳的最大元素个数
swap() 交换两个map

共有8个迭代器: begin、end、rbegin、rend 、cbegin、cend、crbegin、crend 两者的区别在于,后面一组一定返回const_iterator, 而前面四个则根据map的类型返回iterator或者const_iterator。const情况下,不允许对值进行修改

map的插入操作

用insert插入pair数据

#include<map>
#include<string>
#include<iostream>
using namespace std;

int main()
{
	map<int, string> mapStudent
	mapStudent.insert(pair<int, string>(1, "amy"));
	mapStudent.insert(pair<int, string>(2, "john"));
	map<int, string>::iterator iter;
	for(iter = mapStudent.begin(); iter!=mapStudent.end(); iter++)
		cout<<iter->first<<''<<iter->second<<endl;
}

用insert函数插入value_type数据

value_type是一个typedef,是迭代器所指对象的类型

#include<map>
#include<string>
#include<iostream>

int main()
{
	map<int, string> mapStudent
	mapStudent.insert(map<int, string>::value_type(1, "amy"));
	mapStudent.insert(map<int, string>::value_type(2, "john"));
	map<int, string>::iterator iter;
	for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
		cout<<iter->first<<''<<iter->second<<endl;
}

用insert函数进行多个插入

  1. 插入单个键值对,并返回插入位置和成功标志,插入位置已经存在值时,插入失败
pair<iterator, bool> insert(const value_type& val);
  1. 在指定位置插入,在不同位置插入效率是不一样的,因为设计到重排
iterator insert(const_iterator position, const value_type& val);
  1. 插入多个
void insert(InputIterator first, InputIterator last);
  1. C++11之后支持列表插入多个
void insert(initializer_list<value_type> li);

用数组方式插入数据

#include<map>
#include<string>
#include<iostream>
using namespace std;
int main()
{
	map<int, string> mapStudent;
	mapStudent[1] = "amy";
	mapStudent[2] = "john";
	map<int, string>::iterator iter;
	for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
		cout<<iter->first<<''<<cout->second<<endl;
}

用insert插入数据时,在数据上会涉及到集合的唯一性这个概念, 即当map中有这个key了这个数据就插入不进去了, 但是数组方式就不同了,它可以覆盖之前关键字对应的值
检验可以用pair的第二个变量来知道是否插入成功。

排序

关于排序,map中的元素时自动按key升序排序,所以不能对map用sort函数, STL中默认是采用小于号来排序的,但是在遇到一些特殊情况时map就不能自动排序了,比如关键字是一个结构体或者自定义类,因为没有小于号操作涉及到的排序就会出现问题
可以用重载小于号仿函数来解决

unordered_map

map底层使用红黑树,而unordered_map底层使用哈希表实现,查询的事件复杂度(从算法上讲)是O(1),用哈希表,因此内部是无序的,数据是按照散列韩素插入的。当我们不需要内部有序时,就可以用这个实现; 也是关联式容器,采用std::pair保存key-value形式的数据;
unordered_map库使用“桶”来存储元素,散列值相同的会被存储在一个桶里,当散列容器中有大量数据时,同一个桶里的数据也会增多,造成访问冲入,降低性能。为了提高散列容器的性能, unordered库会在插入元素时自动增加桶的数量,不需要用户指定, 但是用户也可以在构造函数或者rehash()中指定最小的桶的数量

另外从占有内存上来说因为unordered_map采用hash结构,所以它的内存会高于map

set/multiset

会自动排序,搜索、移除和插入拥有对数复杂度。 都以红黑树作为底层实现,set与map的不同在于set中的元素即是键值又是实值,set不匀速有两个元素有相同的键值,不能通过set的迭代器区修改set元素,当对容器中的元素进行插入或删除时, 操作之前的所有迭代器在操作之后依然有效

同样,由于set元素时排好序的,且默认为升序,因此当set集合中的元素为结构体或自定义类时,该结构体或自定义类必须实现<的重载

multiset和set的差别唯一就是multiset允许键值重复

set常用成员函数

  1. begin()–返回指向第一个元素的迭代器

  2. clear()–清除所有元素

  3. count()–返回某个值元素的个数

  4. empty()–如果集合为空,返回true

  5. end()–返回指向最后一个元素的迭代器

  6. equal_range()–返回集合中与给定值相等的上下限的两个迭代器

  7. erase()–删除集合中的元素

  8. find()–返回一个指向被查找到元素的迭代器

  9. get_allocator()–返回集合的分配器

  10. insert()–在集合中插入元素

  11. lower_bound()–返回指向大于(或等于)某值的第一个元素的迭代器

  12. key_comp()–返回一个用于元素间值比较的函数

  13. max_size()–返回集合能容纳的元素的最大限值

  14. rbegin()–返回指向集合中最后一个元素的反向迭代器

  15. rend()–返回指向集合中第一个元素的反向迭代器

  16. size()–集合中元素的数目

  17. swap()–交换两个集合变量

  18. upper_bound()–返回大于某个值元素的迭代器

  19. value_comp()–返回一个用于比较元素间的值的函数

set的insert函数返回值为一个对组(pair): 对组的第一个值first为set类型的迭代器:若插入成功,迭代器指向该元素,若插入失败,迭代器指向之前已经存在的元素; 对组的第二个值seconde为bool类型:若插入成功,bool值为true,若插入失败,bool值为false

multiset的insert函数返回值为multiset类型的迭代器,指向新插入的元素。multiset允许插入相同的值,因此插入一定成功,不需要返回bool类型。

unordered_set

unordered_set和unordered_map内部实现是基于哈希表(hashtable),两者的公共接口大致相同,以unordered_set为例:
使用unordered_set需要包含#include<unordered_set>头文件

下篇主要就学习红黑树,set和multiset的区别就在与红黑树的插入方式一个时insert_uniqueinsert_equal, 而set和map的区别是map的所有元素都是pair而set的键值就是实值
set和map的几乎所欲行为都只是转调用RB-tree的操作行为而已

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STL源码——关联式容器及其底层红黑树实现(上) 之 关联式容器详细介绍 的相关文章

随机推荐

  • 1.1 计算机的发展与应用

    一 计算机的发展 1 计算机的发展 1 计算机的奠基人 艾兰 图灵 4个贡献 图灵机 可计算性理论 人工智能之父 图灵奖 冯 诺依曼 5个贡献 EDVAC 存储程序 现代计算机的基本结构 计算机之父 五部分 2 第一台 首台通用电子计算机
  • readme for esoe tools

    Pack hta Pack hta is a tool of ESOE to pack js files It s also a demo of ESOE It has below features file New Open Saveed
  • L->data 与 L.data比较

    L gt data 与 L data比较 当L是结构体 类的 指针时 用L gt data指明结构体中的变量 面向对象中 类的对象 而当L data则是结构体变量 类的对象 用L data表示
  • docker 容器绑定hosts

    问题 最近有个需求需要在docker容器里进行hosts绑定 尝试了将hosts 写在Dockerfile里 构建出镜像 但是启动容器后绑定的hosts会丢失 而且手动进入容器绑定hosts后 重启容器后hosts也会丢失 原因 简单的说
  • tensorflow的归一化与梯度下降

    代码 coding utf 8 By author MZ import numpy as np from sklearn datasets import load boston import tensorflow as tf from sk
  • Linux下查询比较大的文件命令

    size medium color blue b Linux下查询很大文件的快速命令 b color size find usr sersync type f size 3k color green size medium 这个命令意思是
  • linux backlog,linux下backlog设置 - 就爱阅读网

    当业务有高并发的情况的时候 需要调整backlog 对于PHP而言 需要注意以下3方面 1 操作系统 sysctl 2 web端 nginx 3 php后端 php fpm 操作系统以Ubuntu为例 编辑默认配置文件 etc sysctl
  • C++: 输入二进制以十进制显示

    C 输入二进制以十进制显示 代码展示 代码展示 输入二进制以十进制显示 include
  • regsvr32 /i hhctrl.ocx出现无法注册

    运行 输入regsvr32 i hhctrl ocx出现无法注册hhctrl ocx 无法找到dllinstall输入点 无法注册这个文件 在另一台电脑c windows system32 itss dll拷这个文件过去另一电脑的同一路径
  • C++派生类含有成员对象构造函数析构函数顺序

    参考博客 传送门1 当类中含有对象成员时 类的构造函数要包含对成员对象的初始化 如果构造函数的成员初始化列表没有包含对成员对象的初始化 系统会自动调用成员对象的无参构造函数 顺序上 先调用成员对象的构造函数 当所有的成员对象都执行了自身类的
  • 【目录贴】关于人生、学习的阶段性总结和小窍门(2021及以前)

    关于人生小窍门 自己总结 杂谈 过往时期 知乎 zhihu com 以小见大 杂记过往历程 杂谈 给本科实验室的分享PPT 知乎 zhihu com 一步一步推演出正确的观念 其实就是用来勉励大家学习的一文 杂谈 给本科实验室的分享PPT
  • VS2010默认库“MSVCRTD“,“LIBCMTD与其他库的使用冲突,请使用/NODEFAULTLIB:library

    vs2010 opencv库运行过程中的问题 链接警告 1 gt LINK warning LNK4098 默认库 MSVCRTD 与其他库的使用冲突 请使用 NODEFAULTLIB library 1 gt LINK warning L
  • c3p0数据库连接池自动重连的配置

    在Tomcat中配置c3p0数据库连接池的时候 如果数据库重启 或者网络原因造成服务器和数据库断开连接 Tomcat便再也不能和数据库连接 除非Tomcat服务重启 本人在使用VPN的时候遇到更换IP后数据库连接访问不到 解决办法是在c3p
  • 最新版抖音(20200624)去水印原理及源码,简单的原理与面临的挑战

    1 打开抖音链接 获取下图的这个item id 2 之后使用这个接口请求就ok了 https www iesdouyin com web api v2 aweme iteminfo item ids 6832178122364816644
  • 2023华为笔试机考题库【无向图染色】

    题目描述 给一个无向图染色 可以填红黑两种颜色 必须保证相邻两个节点不能同时为红色 输出有多少种不同的染色方案 输入描述 第一行 输入M 图中节点数 N 边数 后续N行格式为 V1 V2表示一个V1到V2的边 数据范围 1 lt M lt
  • linux内核-系统调用execve()

    读者在linux内核 系统调用fork vfork与clone中已经看到 进程通常是按其父进程的原样复制出来的 在多数情况下 如果复制出来的子进程不能与父进程分道扬镳 走自己的路 那就没多大意义 所以 执行一个新的可执行程序是进程生命历程中
  • GPU-Z

    TechPowerUp GPU Z GPU Z简介 硬件网站TechPowerUp现在又提供了一个类似的工具 用于显卡识别的GPU Z GPU Z是一款显卡测试的比较专业的软件 绿色免安装 界面直观 运行后即可显示GPU核心 以及运行频率
  • HBase(一)——HBase介绍

    HBase介绍 1 关系型数据库与非关系型数据库 1 关系型数据库 关系型数据库最典型的数据机构是表 由二维表及其之间的联系所组成的一个数据组织 优点 1 易于维护 都是使用表结构 格式一致 2 使用方便 SQL语言通用 可用于复杂查询 3
  • 正则表达式验证身份证号码

  • STL源码——关联式容器及其底层红黑树实现(上) 之 关联式容器详细介绍

    在侯捷老师源码剖析一书中对关联式进行源码剖析前先花了不少篇幅介绍红黑树的原理 这是因为关联式容器的底层依赖于RB Tree实现 因此想尝试在下篇剖析红黑树的源码 在此之前 先复习一下各个关联式容器的方法及容器之间的不同之处或许对红黑树的剖析