Map以自定义类做为键值

map在STL中的定义

 

template <class Key, class T, class Compare = less<Key>, class Alloc = alloc>

 第一个参数Key是关键字类型

第二个参数T是值类型

第三个参数Compare是比较函数(仿函数)

第四个参数是内存配置对象

 

map内部存储机制实际是以红黑树为基础,红黑树在插入节点时,必须依照大小比对之后在一个合适的位置上执行插入动作。所以作为关键字,起码必须有“<”这个比较操作符。我们知道,int,float,enum,size_t等等简单关键字,都有内置的比较函数,与map搭配无论是插入还是查找,都没什么问题。但是作为复杂数据类型,如果没有明确定义“<”比较操作符,就不能与map直接搭配使用,除非我们自己定义第三个参数。

在选择map的关键字时,注意以下两点,同时这两点也是改错的方法:

a) 关键字明确定义“<”比较操作符

b) 没有“<”比较操作符,自定义仿函数替代第三个参数Compare,该仿函数实现“()”操作符,提供比较功能。插入时各节点顺序以该仿函数为纲。

 

以std::pair为关键字掺入map
下面我们先写一个有错误的函数,在分析错误原因之后,逐步进行修正。

#include <map>
int main()
{
       std::map<std::pair<int, int>, int> res;
       res.insert(std::make_pair(12,33), 33);
}

 这个程序一定失败,如果非要如此使用,上述a方法显然不适合,std::pair是已定义好的结构体不可修改。只能使用b方法了,定义一个比较类改造如下:

[cpp] view plaincopy
print?
  1. #include <map>  
  2.   
  3. struct comp  
  4.   
  5. {  
  6.   
  7.        typedef std::pair<intint> value_type;  
  8.   
  9.        bool operator () (const value_type & ls, const value_type &rs)  
  10.   
  11.        {  
  12.   
  13.               return ls.first < rs.first || (ls.first == rs.first && ls.second < rs.second);  
  14.   
  15.        }  
  16.   
  17. };  
  18.   
  19. int main()  
  20.   
  21. {  
  22.   
  23.        std::map<std::pair<intint>, int, comp> res;  
  24.   
  25.        res.insert(std::make_pair(std::make_pair(12,33), 33));  
  26.   
  27.        res.insert(std::make_pair(std::make_pair(121,331), 331));  
  28.   
  29.        res.insert(std::make_pair(std::make_pair(122,332), 332));  
  30.   
  31.         
  32.   
  33.        std::map<std::pair<intint>, int, comp>::iterator it = res.find(std::make_pair(121,331));  
  34.   
  35.        if (it == res.end())  
  36.   
  37.               printf("NULL"n");  
  38.   
  39.        else  
  40.   
  41.               printf("%d %d %d "n", it->first.first, it->first.second, it->second);  
  42.   
  43.     return 0;  
  44.   
  45. }  

以结构体或类为关键字插入map

 

[cpp] view plaincopy
print?
  1. #include <map>  
  2.   
  3. struct st  
  4.   
  5. {  
  6.   
  7.        int a, b;  
  8.   
  9.        st():a(0), b(0){}  
  10.   
  11.        st(int x, int y):a(x), b(y){}  
  12.   
  13. };  
  14.   
  15. int main()  
  16.   
  17. {  
  18.   
  19.        std::map<struct st, int> res;  
  20.   
  21.        res.insert(std::make_pair(st(1,2), 12));  
  22.   
  23.        res.insert(std::make_pair(st(30,4), 34));  
  24.   
  25.        res.insert(std::make_pair(st(5,6), 56));  
  26.   
  27.         
  28.   
  29.        std::map<struct st, int>::iterator it = res.find(st(30,4));  
  30.   
  31.        if (it == res.end())  
  32.   
  33.               printf("NULL"n");  
  34.   
  35.        else  
  36.   
  37.               printf("first:%d second:%d %d"n", it->first.a, it->first.b, it->second);  
  38.   
  39.        return 0;  
  40.   
  41. }  

编译这个程序也是错误的,错误意思大概也是没有定义“<”比较函数。因为struct st是我们自己定义的结构体,所以修改这个程序可以使用上面ab两种方法。我们先谈第一种,第一次修改时我也搞错了,我是这样定义比较函数的。
[cpp] view plaincopy
print?
  1. struct st  
  2.   
  3. {  
  4.   
  5.        int a, b;  
  6.   
  7.        st():a(0), b(0){}  
  8.   
  9.        st(int x, int y):a(x), b(y){}  
  10.   
  11. bool operator < (const struct st &rs) {return (this->a < rs.a || (this->a == rs.a && this->b < rs.b));}  
  12.   
  13. };  

按照这个改动再次编译程序还是错误,有个如下这样的提示:

/usr/include/c++/3.2.3/bits/stl_function.h:197: passing `const st' as `this' argument of `bool st::operator<(const st&)' discards qualifiers

       为什么会出现这个 问题呢?我们深入STL的源代码看下。既然说是/usr/include/c++/3.2.3/bits/stl_function.h197行出了问题,且看这行是什么。

   193 /// One of the @link s20_3_3_comparisons comparison functors@endlink.

   194 template <class _Tp>

   195 struct less : public binary_function<_Tp,_Tp,bool>

   196 {

   197       bool operator()(const _Tp& __x, const _Tp& __y) const { return __x < __y; }

   198 };

 

struct st中的“<”在编译后真正是什么样子呢?大概是bool operator < (struct st &ls, const struct st &rs)。在less调用这个比较符时,它都是以const方式传入,不可能再以非const方式调用,故出错。修正如下

struct st

{

       int a, b;

       st():a(0), b(0){}

       st(int x, int y):a(x), b(y){}

       friend bool operator < (const struct st &ls, const struct st &rs);

};

inline bool operator < (const struct st &ls, const struct st &rs)

{return (ls.a < rs.a || (ls.a == rs.a && ls.b < rs.b));}

 以友联函数代替函数内部定义的比较操作符,STL内部也多是以这种方式定义的。如果我非要以内部定义的方式呢?可以使用b方法,我们自定义一个比较仿函数,替代默认的less

插入函数返回值

       map容器中插入数据有很多函数可用,这里只讨论最普通的insert操作,在STL中它是这样定义的。

       pair<iterator, bool> insert(const value_type& x);

       map容器不允许键值重复,在执行插入操作后,可以凭借该返回值获取操作结果。返回值是一个迭代器和布尔值的键值对,迭代器指向map中具有该值的元素,布尔值表示是否插入成功。如果布尔值为true,表示插入成功,则迭代器为新插入值在map中的位置;布尔值为false,表示插入失败(已经存在该值),迭代器为原有值在map中的位置。

 

 

[cpp] view plaincopy
print?
  1. #include <map>  
  2. #include <iostream>  
  3. using namespace std;  
  4.   
  5. class Key  
  6. {  
  7. public:  
  8.     Key();  
  9.     Key(int v);  
  10.     int _key;  
  11.     ~Key();  
  12.     /*重载<作为成员函数不行,两个操作数都要求是const*/  
  13.     //bool operator <(const Key& key);  
  14. };  
  15. bool operator <(const Key &key1,const Key &key2)  
  16. {  
  17.     if(key1._key<key2._key)  
  18.         return true;  
  19.     else  
  20.         return false;  
  21. }  
  22. Key::Key()  
  23. {  
  24. }  
  25. Key::Key(int v)  
  26. {  
  27.     _key=v;  
  28. }  
  29. Key::~Key()  
  30. {  
  31. }  
  32.   
  33. void main()  
  34. {  
  35.       
  36.     map<Key,int> ClassMap;  
  37.     Key one(1);  
  38.     ClassMap.insert(make_pair(one,1));  
  39.     Key two(2);  
  40.     ClassMap.insert(make_pair(two,2));  
  41.     Key three(3);  
  42.     ClassMap.insert(make_pair(three,3));  
  43.     map<Key,int>::iterator itor=ClassMap.begin();  
  44.     while(itor!=ClassMap.end())  
  45.     {  
  46.         cout<<itor->first._key<<" ~~ "<<itor->second<<endl;  
  47.         ++itor;  
  48.     }  
  49. }  

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

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

相关文章

“基于深度学习的目标检测跟工业机器人结合”实现过程

基于深度学习的目标检测技术在工业机器人中的应用&#xff0c;可以帮助机器人实现自动化的目标检测和识别任务。以下是基于深度学习的目标检测与工业机器人结合的一般实现过程&#xff1a; 1. 数据采集和准备&#xff1a; 首先&#xff0c;收集和准备用于训练深度学习模型的数据…

小规模流处理kata。 第2部分:RxJava 1.x / 2.x

在第1部分&#xff1a;线程池中&#xff0c;我们设计并实现了相对简单的系统&#xff0c;用于实时处理事件。 确保您已阅读上一部分&#xff0c;因为它包含一些我们将重用的类。 以防万一这是要求&#xff1a; 一个系统每秒传送约一千个事件。 每个Event至少具有两个属性&…

java 计算信度,11.5.2 评分者信度实例分析

11.5.2 评分者信度实例分析【例11.5】 某校学生举办歌唱大赛&#xff0c;请5位评委老师为最终进入决赛的6名同学评定等级&#xff0c;结果如表11-10所示&#xff0c;请计算其信度。表11-10 歌唱大赛评定等级结果学生教师A1A2A3A4A5A6A344335B434343C233253D445344E324333解&a…

JAVA 类加载 随记

视频: https://www.bilibili.com/video/av29502877 1 JVM把Class加载到内存当中&#xff0c;检验解析初始化。默认使用的懒加载方式。 以下步骤是并行执行 可以把加载源看成JAVA配置文件。 解析&#xff1a; 符号引用&#xff1a; 类名&#xff0c;基本类型 直接引用&#xff…

Linux IO实时监控iostat命令详解

简介 iostat主要用于监控系统设备的IO负载情况&#xff0c;iostat首次运行时显示自系统启动开始的各项统计信息&#xff0c;之后运行iostat将显示自上次运行该命令以后的统计信息。用户可以通过指定统计的次数和时间来获得所需的统计信息。 语法 iostat [ -c ] [ -d ] [ -h ] […

打破冷漠僵局文章_研究僵局–第2部分

打破冷漠僵局文章调查死锁时最重要的要求之一就是要研究死锁。 在我的上一个博客中&#xff0c;我写了一些名为DeadlockDemo代码&#xff0c;该代码使用一堆线程在一系列银行账户之间转移随机数&#xff0c;然后陷入僵局。 该博客运行该代码以演示获取线程转储的几种方法。 线…

七牛云php20m文件上传不了,七牛云存储 - 用php上传图片,我在本地测试,用php 接口,不成功...

七牛反馈显示信息说明已经成功了&#xff0c;但是在七牛空间显示的文件却不完整请问这是为什么啊&#xff1f;&#xff01;&#xff01;测试文件如下&#xff0c;本地localhost测试&#xff1a;require_once("qiniu/io.php");require_once("qiniu/rs.php")…

洛谷 P2463 [SDOI2008]Sandy的卡片 解题报告

P2463 [SDOI2008]Sandy的卡片 题意 给\(n(\le 1000)\)串&#xff0c;定义两个串相等为“长度相同&#xff0c;且一个串每个数加某个数与另一个串完全相同”&#xff0c;求所有串的最长公共子串&#xff0c;每个串长\(\le 101\)&#xff0c;值域\(\in [0,1864]\) 先差分一下&…

linux和windows的进程的虚拟地址空间

昨晚看到了深夜&#xff0c;终于对进程的虚拟地址空间有了个大致的了解&#xff0c;很激动&#xff0c;也很欣慰。回头想来&#xff0c;一个程序员&#xff0c;真的应该知道这些知识&#xff0c;否则还真不太称职。 首先告诉大家&#xff0c;我后面提到的这些知识在《windows核…

安装Red Hat Container Development Kit 2.2版本

当应用程序开发人员或架构师负责探索容器化应用程序提供的可能性时&#xff0c;没有比Red Hat容器开发套件&#xff08;CDK&#xff09;容易的了。 Red Hat CDK具有本地OSX&#xff0c;Linux或Windows环境所需的所有Cloud工具&#xff0c;并且已预先配置了一些容器供您浏览。 …

php_sapi常量,PHP常量PHP_SAPI与函数php_sapi_name()简介,PHP运行环境检测

php_sapi_name() 是用来检测PHP运行环境的函数。该函数返回一个描述PHP与WEB服务器接口的小写字符串。例如&#xff1a;aolserver,apache,apache2filter,apache2handler,caudium,cgi(until PHP 5.3),cgi-fcgi,cli,continuity,embed,isapi,litespeed,milter,nsapi,phttpd,pi3web…

怎么学习正则表达式?(正则的使用心得)

以前使用正则是不会自己去学或者去了解怎么实现正则的语法的&#xff0c;感觉好难懂的样子&#xff0c;于是拖到现在 其实正则不是我想象中的那么难&#xff0c;至少入门还是比较简单。我刚学习了一些比较简单的&#xff0c;谈谈我对正则的理解以及使用心得&#xff0c;希望能帮…

java+解析占位符,如何告诉Spring使用Java映射来解析属性占位符?

Spring提供了一个MapPropertySource,您可以在ApplicationContext的环境中注册(您需要一个大多数ApplicationContext实现提供的ConfigurableEnvironment).解析器(按顺序)使用这些已注册的PropertySource值来查找占位符名称的值.这是一个完整的例子&#xff1a;ConfigurationComp…

UOJ207 共价大爷游长沙

考虑到路径是有向的&#xff0c;不是很好维护。 如果路径无向的话&#xff0c;可以直接转化为链加和查询操作。 既然有向的话&#xff0c;不妨考虑一波hash。 对于一组询问x,y&#xff0c;可以把树划分为两颗子树。 合法显然需要满足 x子树的起点的hashy子树的终点的hash x子树…

mysql select null 0,查询值中为NULL,在MySQL中产生0.00

我有一个动态编写的查询(通过Joomla的OO PHP)将一些值插入MySQL数据库.用户填写的表单上有一个字段用于金额,如果它们留空,我希望进入系统的值为NULL.我已经将错误日志中的查询写出来了;这是查询的样子&#xff1a;INSERT INTO arrc_Voucher(VoucherNbr,securityCode,sequentia…

oracle adf_Oracle ADF移动世界! 你好!

oracle adf您好&#xff0c;ADF Mobile&#xff0c;世界&#xff01; 您可能已经知道... ADF Mobile在这里&#xff01; 以下是一些链接&#xff0c;这些链接会让您有宾至如归的感觉。 ADF Mobile主页&#xff1a; http://www.oracle.com/technetwork/developer-tools/adf/o…

线段树||BZOJ1593: [Usaco2008 Feb]Hotel 旅馆||Luogu P2894 [USACO08FEB]酒店Hotel

题面&#xff1a;P2894 [USACO08FEB]酒店Hotel 题解&#xff1a;和基础的线段树操作差别不是很大&#xff0c;就是在传统的线段树基础上多维护一段区间最长的合法前驱&#xff08;h_&#xff09;&#xff0c;最长合法后驱&#xff08;t_&#xff09;&#xff0c;一段中最长的合…

Linux内存管理详解

前一段时间看了《深入理解Linux内核》对其中的内存管理部分花了不少时间&#xff0c;但是还是有很多问题不是很清楚&#xff0c;最近又花了一些时间复习了一下&#xff0c;在这里记录下自己的理解和对Linux中内存管理的一些看法和认识。 我比较喜欢搞清楚一个技术本身的发展历程…

JavaOne 2016 Essentials:7个您不容错过的事件和会话

参加JavaOne吗&#xff1f; 确保您不会错过这些活动 又到了每年的这个时候。 旧金山一年一度的Java假期即将来临&#xff0c;全市发生了超过400场会议和活动。 由于所有这些内容和新体验都一次发生&#xff0c;因此很容易就无法跟踪正在发生的事情。 在这篇文章中&#xff0c…

任务18:控制反转

控制反转 实现你的依赖&#xff0c;采用什么依赖&#xff0c;不由你自己决定&#xff0c;这个控制交给IOC容器。 这里所有的实现都不由你自己决定&#xff0c;我们只需要传给你就可以了。谁来传呢&#xff1f;容器来传给他 内存的Repository&#xff0c;这里实现的比较简单。 这…