【高阶数据结构】map和set的介绍和使用 {关联式容器;键值对;map和set;multimap和multiset;OJ练习}

这篇具有很好参考价值的文章主要介绍了【高阶数据结构】map和set的介绍和使用 {关联式容器;键值对;map和set;multimap和multiset;OJ练习}。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

map和set的介绍和使用

一、关联式容器

关联式容器和序列式容器是C++ STL中的两种不同类型的容器。

  • 关联式容器是基于键值对的容器,其中每个元素都有一个唯一的键值,可以通过键值来访问元素。关联式容器包括set、multiset、map和multimap。

  • 序列式容器是基于元素序列的容器,其中元素按照一定的顺序排列,可以通过元素的位置来访问元素。序列式容器包括vector、deque、list和array。

  • 关联式容器和序列式容器的主要区别在于它们的存储方式和访问方式。关联式容器使用二叉搜索树等数据结构来存储元素,可以快速地查找元素,但是插入和删除元素的效率较低。序列式容器使用数组或链表等数据结构来存储元素,可以快速地插入和删除元素,但是查找元素的效率较低。

在选择使用关联式容器还是序列式容器时,需要根据具体的需求来进行选择。如果需要按照键值来查找并访问元素,可以选择关联式容器;如果需要按照元素的位置来访问元素,可以选择序列式容器。

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

二、键值对

【高阶数据结构】map和set的介绍和使用 {关联式容器;键值对;map和set;multimap和multiset;OJ练习},数据结构和算法,数据结构,c++,map,set

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

在C++中的键值对结构是pair,它是一个类模版。下面是SGI-STL中关于键值对的定义:

template <class T1, class T2>
struct pair
{
	typedef T1 first_type;
	typedef T2 second_type;
	T1 first; //代表键值key
	T2 second; //表示与key对应的信息value
	pair(): first(T1()), second(T2())
	{}
	pair(const T1& a, const T2& b): first(a), second(b)
	{}
};

注意:pair类在头文件<utility>中声明,<utility>又被头文件<map>包含。


三、set的介绍和使用

3.1 set的介绍

  1. set是按照一定次序存储元素的容器,底层实际就是平衡二叉搜索树(红黑树)的K模型。

  2. set中的元素不能在容器中修改(元素总是const),但是可以从容器中插入或删除它们。

  3. 在内部,set中的元素总是按照其内部比较对象(仿函数)所指示的特定严格弱排序准则进行排序。

注意:

  1. set中只放键值key,插入元素时,只需要插入key即可,不需要构造键值对。
  2. set中的元素不可以重复,因此可以使用set进行去重
  3. 使用set的迭代器遍历set中的元素,可以得到有序序列
  4. set中查找某个元素,时间复杂度为:log_2 n
  5. set中的元素不允许修改,因为修改set中的元素会破坏二叉搜索树结构。

set的模板参数列表

【高阶数据结构】map和set的介绍和使用 {关联式容器;键值对;map和set;multimap和multiset;OJ练习},数据结构和算法,数据结构,c++,map,set

  • T: set中存放元素的类型,也就是键值key的类型。
  • Compare:比较对象(仿函数),set中元素默认按照小于来比较。
  • Alloc:set中元素空间的管理方式,默认使用STL提供的空间配置器管理。

3.2 set的使用

3.2.1 Constructor

【高阶数据结构】map和set的介绍和使用 {关联式容器;键值对;map和set;multimap和multiset;OJ练习},数据结构和算法,数据结构,c++,map,set


3.2.2 Iterator

【高阶数据结构】map和set的介绍和使用 {关联式容器;键值对;map和set;multimap和multiset;OJ练习},数据结构和算法,数据结构,c++,map,set

注意:set的迭代器是按照搜索二叉树的中序遍历顺序遍历set中的元素,所以当比较对象默认为Less时:set正向迭代器的遍历结果是升序序列;逆向迭代器的遍历结果是降序序列;


3.2.3 Modifiers

insert && erase

【高阶数据结构】map和set的介绍和使用 {关联式容器;键值对;map和set;multimap和multiset;OJ练习},数据结构和算法,数据结构,c++,map,set

【高阶数据结构】map和set的介绍和使用 {关联式容器;键值对;map和set;multimap和multiset;OJ练习},数据结构和算法,数据结构,c++,map,set


swap

【高阶数据结构】map和set的介绍和使用 {关联式容器;键值对;map和set;multimap和multiset;OJ练习},数据结构和算法,数据结构,c++,map,set

调用set::swap完成交换后,容器中的元素是调用前 x 中的元素。所有的迭代器,引用,指针对交换后的对象仍然有效。

底层原理:set::swap是浅交换,只是将两个set中的root指针做了交换。


3.2.4 Operations

find

【高阶数据结构】map和set的介绍和使用 {关联式容器;键值对;map和set;multimap和multiset;OJ练习},数据结构和算法,数据结构,c++,map,set

返回值:找到了返回元素的迭代器;找不到返回set::end;


count

【高阶数据结构】map和set的介绍和使用 {关联式容器;键值对;map和set;multimap和multiset;OJ练习},数据结构和算法,数据结构,c++,map,set


lower_bound && upper_bound

【高阶数据结构】map和set的介绍和使用 {关联式容器;键值对;map和set;multimap和multiset;OJ练习},数据结构和算法,数据结构,c++,map,set

返回值:返回容器中>=val的第一个元素的迭代器

【高阶数据结构】map和set的介绍和使用 {关联式容器;键值对;map和set;multimap和multiset;OJ练习},数据结构和算法,数据结构,c++,map,set

返回值:返回容器中>val的第一个元素的迭代器


equal_range
【高阶数据结构】map和set的介绍和使用 {关联式容器;键值对;map和set;multimap和multiset;OJ练习},数据结构和算法,数据结构,c++,map,set

返回值:用键值对pair返回容器中等于val的元素的迭代器范围,其中first<=valsecond>val


3.3 multiset的介绍和使用

multiset:允许存在键值相等的元素(允许键值冗余)

【高阶数据结构】map和set的介绍和使用 {关联式容器;键值对;map和set;multimap和multiset;OJ练习},数据结构和算法,数据结构,c++,map,set

multiset和set拥有相同的成员函数,但用法略有不同:

  1. multiset::find:如果有多个键值相等的元素,返回中序遍历中的第一个。
  2. multiset::erase(val):如果有多个键值相等的元素,将所有值为val的元素全部删除。
  3. multiset::count(val):统计容器中值为val的元素个数。

测试代码:

void Test1(){
  multiset<int> ms = {1,4,2,6,3,7,4,2,4,1}; //c++11语法:初始化列表构造
  multiset<int>::iterator it = ms.begin();
  while(it != ms.end())
  {    
    cout << *it << " ";    
    ++it;    
  }    
  cout << endl;    
    
  cout << "test_erase:";    
  ms.erase(1);    
  it = ms.begin(); 
  //......
  //遍历输出ms
  cout << endl;    
    
  cout << "test_find:";
  auto pos = ms.find(4);
  //......
  //从pos开始遍历输出ms
  cout << endl;
    
  cout << "test_count:";
  cout << ms.count(4) << endl;  
}

运行结果:

【高阶数据结构】map和set的介绍和使用 {关联式容器;键值对;map和set;multimap和multiset;OJ练习},数据结构和算法,数据结构,c++,map,set


四、map的介绍和使用

4.1 map的介绍

  1. map是按照特定次序存储<key,value>键值对的容器,底层实际就是平衡二叉搜索树(红黑树)的KV模型。

  2. 在map中,键值key通常用于排序和惟一标识元素,而值value中存储与此键值key关联的内容。键值key和值value的类型可能不同,并且在map的内部,key与value通过成员类型value_type绑定在一起,value_type是键值对pair类型。【高阶数据结构】map和set的介绍和使用 {关联式容器;键值对;map和set;multimap和multiset;OJ练习},数据结构和算法,数据结构,c++,map,set

  3. 在内部,map中的元素总是按照键值key进行比较排序的。

map的模版参数列表

【高阶数据结构】map和set的介绍和使用 {关联式容器;键值对;map和set;multimap和multiset;OJ练习},数据结构和算法,数据结构,c++,map,set

  • key: 键值对中key的类型
  • T: 键值对中value的类型
  • Compare: 比较器的类型,map中的元素是按照key来比较的,缺省情况下按照小于来比较,一般情况下(内置类型元素)该参数不需要传递,如果无法比较时(自定义类型),需要用户自己显式传递比较规则(一般情况下按照函数指针或者仿函数来传递)
  • Alloc:通过空间配置器来申请底层空间,不需要用户传递,除非用户不想使用标准库提供的空间配置器

注意:在使用map时,需要包含头文件<map>。


4.2 map的使用

map和set的使用大体相同,不做过多介绍。举两个例子具体来看:在上一章节《二叉搜索树》的KV模型应用部分,有两个应用实例:用二叉搜索树的KV模型实现字典和单词计数器。现在我们用map来实现:

4.2.1 例一:Dictionary
void Dictionary(){
  map<string, string> dict;
  //map存储的元素是键值对pair,有以下几种pair的构造插入方法:
  //1.匿名对象构造法
  dict.insert(pair<string, string>("string", "字符串"));
  //2.typedef类型重命名,缩短类型名
  typedef pair<string, string> DictKV;
  dict.insert(DictKV("peach", "桃子")); 
  //3.通过make_pair函数模版构造键值对(推荐)   
  dict.insert(make_pair("dictionary", "字典"));    
  dict.insert(make_pair("temporary", "短暂的"));
  dict.insert(make_pair("declaration", "声明"));    
    
  //map的迭代器遍历
  //map<string, string>::iterator it = dict.begin();                   
  auto it = dict.begin(); //map迭代器的类型过长,通过auto自动识别类型    
  while(it != dict.end())                        
  {    
    //cout << (*it).first << ":" << (*it).second << endl; //解引用后通过.访问pair的成员    
    cout << it->first << ":" << it->second << endl;//直接通过->访问pair的成员(推荐)  
    ++it;    
  } 
   
  //范围for:
  //for(pair<const string, string> &e : dict) //map存储的元素是键值对pair,注意key是const类型
  for(auto &e : dict) //临时变量e应该取引用,避免发生拷贝构造,浪费资源   
  {    
    cout << e.first << ":" << e.second << endl; 
  }
    
  string input;
  while(cin >> input)                     
  {
    auto ret = dict.find(input); //传入key值,返回对应元素(pair)的迭代器
    if(ret != dict.end()) //找不到返回map::end
    {
      cout << ret->first << ":" << ret->second << endl;
    }
    else{
      cout << "There is no such word!" << endl;
    }
  }
}

make_pair

【高阶数据结构】map和set的介绍和使用 {关联式容器;键值对;map和set;multimap和multiset;OJ练习},数据结构和算法,数据结构,c++,map,set

【高阶数据结构】map和set的介绍和使用 {关联式容器;键值对;map和set;multimap和multiset;OJ练习},数据结构和算法,数据结构,c++,map,set

  1. make_pair是一个函数模版,作用是利用传入的两个参数构造键值对pair并返回(传值返回)。

  2. 利用了函数模版的隐式实例化:通过传入的参数类型自动推导pair的模版参数。

  3. make_pair在头文件<utility>中声明,<utility>又被头文件<map>包含。


4.2.2 例二:WordCounter
void WordCounter(){
  map<string, int> counter;
  string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜","苹果", "香蕉", "苹果", "香蕉"};
  //方法一:上一章讲过的方法
  //for(string &e : arr)
  //{
  //  auto ret = counter.find(e);
  //  if(ret != counter.end())
  //  {
  //    ++ret->second; 
  //  } 
  //  else{
  //    counter.insert(make_pair(e,1));                                                                                          
  //  }
  //}
    
  //方法二:operator[](推荐)
  for(string &e : arr)
  {
    //如果e不在counter中,先插入pair(e,int()),再对返回value(次数)++;
    //如果e在counter中,返回value(次数)的引用,次数++;
    ++counter[e];
  }
  for(auto &e : counter)
  {
    cout << e.first << ":" << e.second << endl;
  }
}

operator[]

【高阶数据结构】map和set的介绍和使用 {关联式容器;键值对;map和set;multimap和multiset;OJ练习},数据结构和算法,数据结构,c++,map,set

  1. map支持operator[],但与vector等连续存储容器的位置下标访问不同,map支持关键字下标访问,[]中填入key值:

  2. 如果map中有这个key,返回对应value的引用。(查找+修改value)

  3. 如果map中没有这个key,会插入一个pair(key,value()),并返回新创建的value的引用。(插入+修改value)

  4. 所谓pair(key,value())使用给定的key和value的默认构造创建的pair键值对。

  5. map::at是一个和operator[]功能相似的成员函数。当key存在时和[]有相同的行为;但当key不存在时,at不会创建新元素而是直接抛异常。

  6. operator[]的底层实现相当于:

    mapped_type& operator[] (const key_type& k)
    {
        return (*((this->insert(make_pair(k,mapped_type()))).first)).second;
    }
    //下面代码的可读性更高,更简洁。
    mapped_type& operator[] (const key_type& k)
    {
        pair<iterator, bool> ret = insert(make_pair(k,mapped_type()));
        return ret.first->second;
    }
    

insert

【高阶数据结构】map和set的介绍和使用 {关联式容器;键值对;map和set;multimap和multiset;OJ练习},数据结构和算法,数据结构,c++,map,set

  1. 如果key已经在map中,插入失败,返回pair(key_iterator, false);
  2. 如果key不在map中,插入成果,返回pair(newkey_iterator, true);

4.3 multimap的介绍和使用

  1. multimap和map的唯一不同就是:map中的key是唯一的,而multimap中允许存在键值相等的元素(允许键值冗余)
  2. 没有重载operator[]:由于键值冗余,无法确定唯一的value。
  3. multimap中的接口可以参考map,功能都是类似的。

五、OJ练习

692. 前K个高频单词

349. 两个数组的交集文章来源地址https://www.toymoban.com/news/detail-680590.html

到了这里,关于【高阶数据结构】map和set的介绍和使用 {关联式容器;键值对;map和set;multimap和multiset;OJ练习}的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 「数据结构」Map&Set

    🎇 个人主页 :Ice_Sugar_7 🎇 所属专栏 :Java数据结构 🎇 欢迎点赞收藏加关注哦! Map和Set是专门用来进行搜索的容器或者数据结构,它们适合动态查找(即在查找时可能会进行一些插入和删除的操作) 我们一般把搜索的数据称为 (Key) ,和对应的称为 值(

    2024年02月22日
    浏览(50)
  • [数据结构]-map和set

    前言 作者 : 小蜗牛向前冲 名言 : 我可以接受失败,但我不能接受放弃   如果觉的博主的文章还不错的话,还请 点赞,收藏,关注👀支持博主。如果发现有问题的地方欢迎❀大家在评论区指正   目录 一、键值对 二、set 1、set的基本知识 2、set的使用  三、map 1、map的基本

    2024年02月04日
    浏览(59)
  • 【数据结构】 Map和Set详解

    Map和set是一种专门用来 进行搜索的容器或者数据结构 ,其搜索的效率与其具体的实例化子类有关。以前常见的 搜索方式有: 直接遍历,时间复杂度为O(N),元素如果比较多效率会非常慢 二分查找,时间复杂度为 ,但搜索前必须要求序列是有序的 上述排序比较适合静态类型的

    2024年02月09日
    浏览(48)
  • Java学数据结构(3)——树Tree & B树 & 红黑树 & Java标准库中的集合Set与映射Map & 使用多个映射Map的案例

    1.B树,阶M,数据树叶上,根的儿子数在2和M之间,除根外,非树叶节点儿子为M/2和M之间; 2.B树的插入引起分裂,B树的删除,引起合并和领养; 3.红黑树,根是黑的,红色节点的儿子必须是黑的,所有路径的黑色节点数相同; 4.红黑树的插入,颜色翻转,单旋转,插入节点定

    2024年02月11日
    浏览(81)
  • 【数据结构】 | java中 map和set 详解

    🎗️ 博客新人,希望大家一起加油进步 🎗️ 乾坤未定,你我皆黑马 我们首先来看一下集合的框架结构: Set实现了Collection接口,Map是一个单独存在的接口。 而下面又分别各有两个类,分别是TreeSet(HashSet)和 HashSet(HashMap) Map和Set的作用是用来查找和搜索的;以后涉及到

    2023年04月10日
    浏览(40)
  • Map、Set和哈希表(数据结构系列14)

    目录 前言: 1.搜索树 1.1概念 1.2插入 1.3查找 1.4删除 1.5二叉搜索树整体代码展示  2. Map和Set的讲解 2.1 Map的说明 2.1.1Map的方法 2.2 Set 的说明 2.2.1Set的方法 3.哈希表 3.1哈希表的概念 3.2哈希冲突 3.3冲突的避免 3.4哈希冲突的解决 3.4.1闭散列 3.4.2开散列 结束语: 这节中小编主要与

    2024年02月07日
    浏览(37)
  • 数据结构 - 7(Map和Set 15000字详解)

    二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树: 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值 它的左右子树也分别为二叉搜索树 int[] array ={5,3,4,1,7,8,2,6,0

    2024年02月06日
    浏览(38)
  • 【1++的数据结构】之map与set(一)

    👍作者主页:进击的1++ 🤩 专栏链接:【1++的数据结构】 像list vector dequeue等这样的容器我们称为序列式容器,原因是由于其底层是线性的数据结构,存储的是元素本身。 关联式容器 与序列式容器的区别在于:关联式容器中存储的是键值对,其数据检索时效率更高。 那么什

    2024年02月11日
    浏览(46)
  • Map,List,Set 等集合以及底层数据结构

    集合类存放于java.util包中。集合类存放的都是对象的引用,而非对象本身。常见的集合主要有三种——Set(集)、List(列表)和Map(映射)。其中,List和Set 都 实现 了 Collection 接口,并且List和Set也是接口,而 Map 为独立接口 。常见的实现类如下: List 的实现类有:ArrayList、

    2024年02月09日
    浏览(46)
  • 数据结构之Map/Set讲解+硬核源码剖析

     💕\\\"活着是为了活着本身而活着\\\"💕 作者:Mylvzi    文章主要内容:数据结构之Map/Set讲解+硬核源码剖析    二叉搜索树又叫二叉排序树,他或者是一颗空树,或者是具有以下性质的树 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值 若它的右子树不为空,

    2024年02月04日
    浏览(52)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包