关联式容器(map,set,multimap,multiset)

关联式概念

  • STL中的部分容器,比如:vector、list、deque、forward_list(C++11)等,这 些容器统称为序列式容器,因为其底层为线性序列的数据结构,里面存储的是元素本身。
  • 关联式容器也是用来存储数据的,与序列式容器不同的是,其里面存储的是<key, value>结构的键值对在数据检索时比序列式容器效率更高。
二叉搜索平衡结构:

关于key有序的序列,时间复杂度O(logN)

  • map<key,value> 要求:key一定不能重复
  • set:key 要求:key一定不可以重复
  • multimap:<key,value> key是可以重复的
  • multiset:key,key可以重复

键值对

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

SGI—STL中键值对的底层实现
 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) {}}; 

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通常被实现为二叉搜索树(更准确的说:平衡二叉搜索树(红黑树))。

在这里插入图片描述

map::insert()

在这里插入图片描述
通过insert插入数据有两种方式

  1. pair<类型,类型>(数据,数据)
  2. make_pair(数据,数据)

还可以通过下标运算符[]
对于map来说,如果我们提供的key不存在的情况下,他就会插入这个数据
因为它的下标运算符的底层是这样实现的

(*((this->insert(make_pair(k,mapped_type()))).first)).second 

如果key已经存在了,他就不会插入

void TestMap()
{map<string, string>m;m.insert(pair<string,string>("宋江","及时雨"));m.insert(pair<string, string>("李逵", "黑旋风"));//pair<iterator,bool>//iterator:代表map中的一个key-value的键值对//bool:insert插入是否成功auto ret = m.insert(make_pair("孙二娘","母夜叉"));if (ret.second){cout << (*ret.first).first << "--->" << ret.first->second << endl;}ret = m.insert(make_pair("李逵", "铁牛"));//key 已经存在不会插入cout << (*ret.first).first << "--->" << ret.first->second << endl;cout << m.size() << endl;cout << m["李逵"] << endl; //把value返回来//用户提供key---->[]返回key所对应的valuem["李逵"] = "铁牛";  //修改valuecout << m["李逵"] << endl;m["林冲"] = "豹子头";cout << m.size() << endl;
}

下标运算符为什么要用insert?
因为如果key不存在的话,返回值就不好返回了,因为如果key存在返回存在的,如果key不存在插入key和一个默认的value

void TestMap2()
{int array[] = { 3, 1, 9, 4, 0, 7, 6, 2, 5 };map<int, int>m;for (auto e : array){m.insert(make_pair(e, e));}//测试按照迭代器方式进行遍历,能否得到一个关于key有序的序列auto it = m.begin();while (it != m.end()){cout << it->first << "---->" << it->second << endl;++it;}cout << endl;for (auto& e : m){cout << e.first << "---->" << e.second << endl;}cout << endl;
}

key是有序的,但是value就不一定
其余的功能演示参考:map的其他功能演示

set

set相关接口的演示

set容器没有下标预算符.
set:key,key一定是唯一的
set 最主要的功能是去重,并排序

测试set

int main()
{int array[] = { 3, 1, 3, 4, 5, 6, 7, 8, 9, 0, 9, 4, 0, 7, 6, 2, 5, 8 };set<int>s;for (auto e : array)s.insert(e);cout << s.size() << endl;for (auto e : s)cout << e << " ";cout << endl;system("pause");return 0;
}

在这里插入图片描述

multimap

multimap基本操作

注意事项

  1. multimap中的key是可以重复的。
  2. multimap中的元素默认将key按照小于来比较
  3. multimap中没有重载operator[]操作
  4. 使用时与map包含的头文件相同

#include #include

void TestMultimap1() 
{multimap<string, string> m; m.insert(make_pair("李逵", "黑旋风")); m.insert(make_pair("林冲", "豹子头")); m.insert(make_pair("鲁达", "花和尚"));// 尝试插入key相同的元素 m.insert(make_pair("李逵", "铁牛")); cout << m.size() << endl;for (auto& e : m)    
cout << "<" << e.first << "," << e.second << ">" << endl;// key为李逵的元素有多少个    cout << m.count("李逵") << endl; return 0; 
}
 void TestMultimap2() {    multimap<int, int> m;for (int i = 0; i < 10; ++i)    m.insert(pair<int, int>(i, i));for (auto& e : m)    cout << e.first << "--->" << e.second << endl; cout << endl;// 返回m中大于等于5的第一个元素 auto it = m.lower_bound(5); cout << it->first << "--->" << it->second << endl;// 返回m中大于5的元素 it = m.upper_bound(5); cout << it->first << "--->" << it->second << endl;}

multiset

multiset的基本操作

multiset:只存储key,key可以重复,关于key有序

测试

int main()
{int array[] = { 3, 1, 3, 4, 5, 6, 7, 8, 9, 0, 9, 4, 0, 7, 6, 2, 5, 8 };multiset<int>s;for (auto e : array)s.insert(e);cout << s.size() << endl;for (auto e : s)cout << e << " ";cout << endl;system("pause");return 0;
}

在这里插入图片描述

底层结构及其模拟实现

底层原理及其模拟实现

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/383155.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

详解 二叉搜索树-----AVL树

二叉搜索树 根结点比左子树中所有结点都大根结点比右子树所有结点都小最小的元素在最左侧最大的元素在最右侧中序遍历有序 具有以上的特征的二叉树就是二叉搜索树也叫二叉排序数 二叉搜索树的操作 查找 要保存查找值的双亲&#xff0c;以便于后续执行插入操作 Node* Find(…

json格式与cJSON函数库

json的格式 键/值对 key:value&#xff0c;用半角冒号分割文档对象 JSON对象写在花括号中&#xff0c;可以包含多个键/值对。数组 JSON 数组在方括号中书写&#xff1a; 数组成员可以是对象&#xff0c;值&#xff0c;也可以是数组(只要有意义)。 { "stars":[ { &qu…

HTTP清晰的学习笔记

HTTP协议—应用层 请求消息(Request)—浏览器给服务器发 包含四部分 请求行&#xff1a;说明请求类型&#xff0c;要访问的资源&#xff0c;以及使用的http版本请求头&#xff1a;说明服务器要使用的附加信息,由键值对构成的空行&#xff1a;空行是必须要有的&#xff0c;即…

如何在 Centos7 x86_64下将vim一键配置为一款强大的C++,IDE

vim功能很强大&#xff0c;但是对于我这样的小白很不友好 然后就有一位大佬&#xff0c;为了辅助我这样的菜鸡&#xff0c;然后供我们一键搞定&#xff0c;在vim畅快编写代码的功能。 首先强烈不推荐在root用户下使用&#xff0c;确保电脑连着网。在普通用户下执行此命令 cur…

详解string容器(应用+模拟实现,string练习题)

为什么要有string容器 string&#xff1a;其实就是一个字符串,c对字符串进行了封装的&#xff0c;封装到一个类里面&#xff0c;这样用户就不用担心开辟空间的问题&#xff0c;只需要往string类里放字符串就可以了&#xff0c;string其实还可以自增长 很多人就会有一个疑问&am…

浅拷贝+引用计数--写时拷贝---模拟实现string容器

引用计数 深拷贝 多个对象共享同一份资源时&#xff0c;最后能够保证该资源只被释放一次 应该由哪个对象释放资源&#xff1f; 由最后一个使用该资源的对象去释放 怎么知道一个对象是最后一个使用该资源的对象&#xff1f; 给一个计数&#xff0c;记录使用该资源对象的个数 实…

详解vector容器(应用+模拟实现,vector相关练习题)

vector容器 动态的顺序表&#xff0c;数组。 vector操作 vector操作及其概念 构造 vector<int>v1;vector<int>v2(10, 5);vector<int>v3(v2);int array[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };vector<int>v4(array, array sizeof(array) / sizeof(a…

详解list容器(应用+模拟实现)

list容器 带头结点的双向循环链表 list操作 list容器的概念及其操作 构造和销毁 list<int>L1;list<int>L2(10, 5);vector<int>v{ 1, 2, 3, 4, 5, 6, 7, 8, 9 };list<int>L3(v.begin(), v.end());list<int>L4(L3);元素访问 cout << L3.…

vector和list容器有哪些区别

这个问题的本质还是在问顺序表和链表的区别 底层结构不同 vector容器list容器一段连续的空间带头结点的双向循环链表 元素访问方式 vector容器list容器支持随机访问—O(1)不支持随机访问—O(N)需要扩容不需要扩容任意位置插入元素----O(N)–搬移元素O(1) 迭代器不同 vector…

复习栈和队列,详解最小栈,栈的弹出压入序列,逆波兰表达式求值

栈和队列的概念 栈:吃进去吐出来 对列&#xff1a;吃进去拉出来 数据结构中的栈和内存中的区别 数据结构中的栈具有后进先出的特性&#xff0c;而内存中的栈是一个内存空间&#xff0c;只不过这个内存空间具与数据结构的栈具有相同的特性。 栈和队列操作 栈和队列基本操作…

详解优先级队列priority_queue(应用+模拟实现)

优先级队列的概念 优先队列是一种容器适配器&#xff0c;根据严格的弱排序标准&#xff0c;它的第一个元素总是它所包含的元素中最大的此上下文类似于堆&#xff0c;在堆中可以随时插入元素&#xff0c;并且只能检索最大堆元素(优先队列中位于顶部的元 素)。优先队列被实现为容…

私人博客定制

项目背景 可行性方面 需求分析&#xff1a; 详细设计&#xff1a; 数据库设计 博客管理API的设计 标签相关API 服务器端的实现 对数据库操作进行封装 对服务器操作进行封装 客户端实现 具体操作 使用markdown 具体实现 测试 项目效果展示 维护 完整代码 项目…

初识c++中的函数模板

函数模板 函数模板概念 函数模板:编译器生成代码的一个规则。函数模板代表了一个函数家族&#xff0c;该函数模板与类型无关&#xff0c;在使用时被参数化&#xff0c;根据实参类型产生函数的特定类型版本。 函数模板格式 //要让这个函数与类型无关 //Add函数模板 template…

深入理解c++中的函数模板

非类型模板参数 模板参数分类类型形参与非类型形参。 类型形参&#xff1a;出现在模板参数列表中&#xff0c;跟在class或者typename之类的参数类型名称。 非类型形参&#xff0c;就是用一个常量作为类(函数)模板的一个参数&#xff0c;在类(函数)模板中可将该参数当成常量来使…

c++中的IO流

c语言中的IO操作 标准类型的输入输出: 输入------>数据来源是通过键盘进行输入输出------>程序中的数据输出到控制台 c语言中: scanf:输入 printf:输出 两个函数的相同点 1 —格式串 2 —不定参数 两个函数的缺陷 1 —用户要提供数据的格式—用户要记忆大量的格式串—…

201301 JAVA2~3级---走格子

请编写一个函数&#xff08;允许增加子函数&#xff09;&#xff0c;计算n x m的棋盘格子&#xff08;n为横向的格子数&#xff0c;m为竖向的格子数&#xff09;沿着各自边缘线从左上角走到右下角&#xff0c;总共有多少种走法&#xff0c;要求不能走回头路&#xff0c;即&…

复习Linux基本操作----常见指令

Linux基本操作 ls命令 ls(list):相当于windows上的文件资源管理器 语法&#xff1a; ls [选项][目录或文件] 功能&#xff1a;对于目录&#xff0c;该命令列出该目录下的所有子目录与文件。对于文件&#xff0c;将列出文件名以及其他信息。 常用选项&#xff1a; -a 列出目…

复习Linux基础操作---权限操作

shell命令以及运行原理 Linux严格意义上说的是一个操作系统&#xff0c;我们称之为“核心&#xff08;kernel&#xff09;“ &#xff0c;但我们一般用户&#xff0c;不能直接使用kernel。而是通过kernel的“外壳”程序&#xff0c;也就是所谓的shell&#xff0c;来与kernel沟…

【剑指offer】_01 (二维数组中的查找)

题目描述 在一个二维数组中&#xff08;每个一维数组的长度相同&#xff09;&#xff0c;每一行都按照从左到右递增的顺序排序&#xff0c;每一列都按照从上到下递增的顺序排序。请完成一个函数&#xff0c;输入这样的一个二维数组和一个整数&#xff0c;判断数组中是否含有该…

再谈c++中的多态

何为多态 多态的概念&#xff1a;通俗来说&#xff0c;就是多种形态&#xff0c;具体点就是去完成某个行为&#xff0c;当不同的对象去完成时会产生出不同的状态。 多态的实现 在继承的体系下 基类中必须有虚函数(被virtual关键字修饰的成员函数)&#xff0c;在派生类中必须…