情景分析
我们想象这样一种情景,我知道某个人的姓名和电话号码,我们既想要通过这个人的姓名得到到这个人的电话,又想能通过这个人的电话,知道这个人的姓名。
这个时候,我们第一个想到的一定是Map
众所周知,map可以通过调用find函数,通过key索引,迅速访问到value值,在此不在赘述
基础解决方案:
对于上面的问题,我们可以有两种解决方案
第一种,我们可以创建两个
map<string, string>
,甚至是一个map<string, string>
不过保存数据保存两遍,我们传入的值就可以都作为key值来直接调用find函数,这种解决方案,适用于你的数据量比较小,或者对内存没有要求。时间复杂度,和find的时间复杂度一样第二种,我们可以创建一个
map<string, string>
,然后判断我们传入的值是key值还是value(也就是姓名还是电话号码),如果是姓名,我们将他作为key值来直接调用find函数,如果是value值,我们可以通过遍历来访问,这样可以节省一些内存,但是牺牲了时间
前面两种方法,都比较简单,但是会造成时间或者空间上的浪费,我们会想,既然能传一个指针,那么可不可以两个都作为指针使用,这样我们同样传两遍,但是传入的数据是指针,可以减少内存的使用,同时又可以调用find函数,也能减少时间复杂度
如果使用两个参数的map,是不可以的,这在大多数人的blog中也可以知道原因,我也不再说明。或者说,你直接试一下就会发现,你的key值如果是一个指针的话,他的地址势必与传入的想要寻找的key值的指针地址不同,永远无法find到
这个时候,我们该如何实现这种骚操作
Map的第三个参数
在官方文档中,map是这样定义的
template < class Key, // map::key_type
class T, // map::mapped_type
class Compare = less<Key>, // map::key_compare
class Alloc = allocator<pair<const Key,T> >//map::allocator_type
> class map;
在此,第一个和第二个参数大家都非常熟悉,我也不再讲解,第四个参数我也还没研究,研究之后我再进行讲解。接下来我们重点来看一下我们今天要用到的第三个参数
查看了map的定义之后,发现map对key的要求就是要定义< operator。为什么map不需要key定义== operator呢?我们觉得,定义< operator用来用来判断两个key的大小,从而决定key在map中排列的次序,而定义==可以用来判断两个key是否相等,从而在使用key引用value的时候用上。
后来查阅了资料,发现定义一个< operator就足够了。当我们使用key来引用value的时候,map采用二分查找法,在map中搜索,如果map找到一个key,发现这个key既不大于我们给的key,也不小于我们给的key,那么,map就认为这两个key相等,从而给出value
熟悉C++的同学,这个时候应该很自然的想到重载,既然我们判断的是key值和传入的值的大小,我们不能直接用STL中定义的< 来比较,那我们是不是可以自己重载运算符,使得我们得以比较我们key值所指向的地址所存的数据,传入的值也是其指向的地址所存的数据,再进行比较,这样就可以实现通过指针来比较
实现方案
struct ptrCmp
{
bool operator()(const TCHAR *a, const TCHAR *b)
{
return _tcscmp(a, b) < 0;
}
};
typedef map<TCHAR *, TCHAR *, PtrCmp> TextResMap;
我们只需要通过这样的方式,来实现运算符的重载,调用find函数时,系统会传入两个指针,然后我们比较两个指针所指向的对象,从而实现通过查找
当然,这个时候你需要注意,你在构造map的时候,有两种方式
map<TCHAR *, TCHAR *, PtrCmp> exampleMap
或者TextResMap exampleMap
此处TCHAR可以根据你自己想要实现的功能自己定义
综上,如有不足,请指教