vc下有2个版本的散列表类,hash_map和unordered_map,hash_map位于stdext命名空间,unordered_map在std命名空间(vs2008及其之后的版本可用),官方推荐使用unordered_map,前者是一个旧的非标版本。

2者使用起来很类似,但构造函数有明显不同。 在使用int之类的值类型作为key的情况下,后几个参数可以使用默认值,无需提供hash function和compare function。但如果需要特殊类型作为散列键值的情况用起来就麻烦很多,比如用字符串string作为散列键值(但如果include了<string>也是无需提供hash function和compare function,很方便)。

template<
    class Key,
    class Ty,
    class Hash = std::hash<Key>,
    class Pred = std::equal_to<Key>,
    class Alloc = std::allocator<std::pair<const Key, Ty> > >
    class unordered_map; template <
   class Key, 
   class Type, 
   class Traits=hash_compare<Key, less<Key> >, 
   class Allocator=allocator<pair <const Key, Type> > >
   class hash_map;  

散列表类有几个概念搞清楚后才能很好的理解这2个构造函数。key键值、value实值、hash值是哈希表最基本的概念,在存储value值的时候,散列表需要将key值转换为hash值(hash值会被用来当做数组下标使用),其类型为无符号整形。key值 --> hash值的映射函数就是hash函数,vc为一些类型的key提供了默认的hash函数,比如int和string。映射函数并不保证key与hash值的映射关系是一一对应的,可能出现多个key值映射到一个hash值的情况。此时我们需要比较函数来解决冲突,用来区分相同hash值下的不同key值。

回到上面的2个构造函数,unordered_map是比较容易理解的,第三个入参【class Hash = std::hash<Key>】,它所需要的类型其实是个函数对象,用来完成散列映射。默认使用了名为hash的函数对象。第四个参数【class Pred = std::equal_to<Key>】,所需要的类型也是函数对象,用来完成hash值冲突后的key值的比较。对这2个参数我们也可以使用自定义的函数对象,比如下面(假设key的类型为int)。另外,string类型比较特殊,后面另说。

struct hashMy
{
    size_t operator()(int _Val) const{return _Val%;}
}; struct equalMy
{    // functor for operator==
    bool operator()(const int _Left, const int _Right) const
    {    // apply operator== to operands
        return (_Left == _Right);
    }
}; std::unordered_map<int,int,hashMy,equalMy> s3;  

而hash_map类的构造函数则是由第三个入参完成hash函数和比较函数2个功能。其默认的函数对象的定义如下

template<class Key, class Traits = less<Key> >
   class hash_compare
   {
   Traits comp;
public:
   const size_t bucket_size = ;
   const size_t min_buckets = ;
   hash_compare( );
   hash_compare( Traits pred );
   size_t operator( )( const Key& _Key ) const;
   bool operator( )( 
      const Key& _Key1,
      const Key& _Key2
   ) const;
   };

注意这个类没有使用equal_to来做hash值冲突后的key值的比较,而是默认使用less函数。据说这是为了提高冲突后的查找效率,当需要判断等于的时候通过!(a < b) && !(b < a)来实现.....自定义的方式如下,假设key是int型。

class hash_compare_my
{
public:
    enum
    { 
        bucket_size = ,
        min_buckets = 
    };
   
    size_t operator( )( const int& _Key ) const{return _Key%;}
    bool operator( )( const int& _Key1,const int& _Key2 ) const
    {
        return (_Key1 < _Key2);
    }
}; stdext::hash_map<int,int,hash_compare_my> t;  

平时经常需要用到string作为key的情况,在不include<string>的情况下,unordered_map会编译失败,我们需要提供自定义的string比较函数,string的hash函数可以复用库中提供的string hash函数。

注意,有include<string> 的情况下不需要提供自定义的hash函数和比较函数。

struct equal_s
{
    bool operator()(const std::string& s1,const std::string& s2)const
    {
        return s1.compare(s2) == ;
    }
};
struct less_s  
{  
    bool operator ()(const std::string & str1, const std::string & str2) const  
    {  
        return str1.compare(str2) < ;  
    }  
}; 
std::unordered_map<std::string,int,std::hash<std::string>,equal_s> s;
stdext::hash_map<std::string,int,stdext::hash_compare<std::string,less_s> > s1;

最后,散列表的插入函数insert有多个重载版本,如果遇到插入的key已经存在则插入操作失败,注意批量插入的重载版本不会显式提示失败。

template<class InputIterator>
    void insert(
        InputIterator _First,
        InputIterator _Last
); pair <iterator, bool> insert(
    const value_type& _Val
);

VC散列表的更多相关文章

  1. 散列表(hash table)——算法导论(13)

    1. 引言 许多应用都需要动态集合结构,它至少需要支持Insert,search和delete字典操作.散列表(hash table)是实现字典操作的一种有效的数据结构. 2. 直接寻址表 在介绍散列 ...

  2. HashTable(散列表)

    最近都在研究数据结构,关于hashtable,或者叫做散列表,过去一直不了解是什么东西,现在终于明白了. 所谓hashtable,就是某组key,通过某个关系(函数),得到一个与之对应的映射值(在计算 ...

  3. &11,散列表

    #1,是什么? 散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构.也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度.这个 ...

  4. [转载] 散列表(Hash Table)从理论到实用(上)

    转载自:白话算法(6) 散列表(Hash Table)从理论到实用(上) 处理实际问题的一般数学方法是,首先提炼出问题的本质元素,然后把它看作一个比现实无限宽广的可能性系统,这个系统中的实质关系可以通 ...

  5. [转载] 散列表(Hash Table)从理论到实用(中)

    转载自:白话算法(6) 散列表(Hash Table)从理论到实用(中) 不用链接法,还有别的方法能处理碰撞吗?扪心自问,我不敢问这个问题.链接法如此的自然.直接,以至于我不敢相信还有别的(甚至是更好 ...

  6. [转载] 散列表(Hash Table) 从理论到实用(下)

    转载自: 白话算法(6) 散列表(Hash Table) 从理论到实用(下) [澈丹,我想要个钻戒.][小北,等等吧,等我再修行两年,你把我烧了,舍利子比钻戒值钱.] ——自扯自蛋 无论开发一个程序还 ...

  7. Java学习笔记(二十)——Java 散列表_算法内容

    [前面的话] 周末,本来打算找人去玩,结果没找到,所以我只好有学习了. 为什么会学习散列表,因为要使用HashMap?因为在做项目的时候,在服务器和客户端需要传输DTO,而传输的属性是动态增加的,所以 ...

  8. [Linux] Linux进程PID散列表

    linux系统中每个进程由一个进程id标识,在内核中对应一个task_struct结构的进程描述符,系统中所有进程的task_struct通过链表链接在一起,在内核中,经常需要通过进程id来获取进程描 ...

  9. JavaScript数据结构——集合、字典和散列表

    集合.字典和散列表都可以存储不重复的值. 在集合中,我们感兴趣的是每个值本身,并把它当作主要元素.在字典和散列表中,我们用 [键,值] 的形式来存储数据. 集合(Set 类):[值,值]对,是一组由无 ...

随机推荐

  1. vue 的小秘密

    1.组件可以通过$refs调用其方法. 2.组件上也可用v-model. <input v-model="something"> == 同等 <input v-b ...

  2. js关闭浏览器窗口及检查浏览器关闭事件

    js关闭浏览器窗口,不弹出提示框.支持ie6+,火狐,谷歌等浏览器,下面以一个示例为大家详细介绍下具体的实现方法,感兴趣的朋友可以参考下   js关闭浏览器窗口 js关闭浏览器窗口,不弹出提示框.支持 ...

  3. 异步请求(ajax,http) 之 逐渐完善的大全

    异步请求在我们的开发之中是经常需要学习和理解的内容,我们将会在这一篇文章中依据不同的语言和环境内容进行归类讲解. JS: ajax是我们最为常用的页面异步请求,在只需要修改部分页面内容而不需要更换全部 ...

  4. MVC框架中的值提供机制(二)

    在MVC框架中存在一些默认的值提供程序模板,这些值提供程序都是通过工厂模式类创建;在MVC框架中存在需要已Factory结尾的工厂类,在值提供程序中也存在ValueProviderFactories工 ...

  5. Qt 中使用智能指针

    教研室的项目,就是用Qt做个图形界面能收发数据就可以了,但是创建数据管理类的时候需要各种new, delete,很小心了但是内存使用量在不断开关程序之后函数会长,由于用的是gcc 4.7.*  所以好 ...

  6. C++轮子队 敏捷冲刺

    团队Github地址:https://github.com/Pryriat/2048.git 敏捷开发——第1天 Alpha阶段第1次Scrum Meeting 敏捷开发起始时间 2018/10/27 ...

  7. JAVA线程死锁

    文件名:DeadThreadByExtend.java 注: 1.起线程的时候用的是start方法,run方法也可以调用,但是仅仅相当于普通调用,在当前线程内执行. 2.synchronized 不能 ...

  8. makefile 学习归纳

    makefile 学习归纳 一直希望 好好整理下 makefile的写法,这在linux编程界是必备技能.下面就好好的说道说道. 可以参考的大神总结 整理 makefile是供make命令执行的 脚本 ...

  9. 列表(增删改查)元组tupe

    增加:有三种,append:在后面添加.Insert按照索引添加,expend:迭代着添加.#append li = ['lishi','alex','lili'] li.append(') prin ...

  10. terminal小工具

    计算器 >bc >quit 显示日历 >cal