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. Tomcat中HTTP与AJP区别

    Tomcat: HTTP与AJP区别 Tomcat服务器通过Connector连接器组件与客户程序建立连接,Connector组件负责接收客户的请求,以及把Tomcat服务器的响应结果发送给客户. 默 ...

  2. Java 子类实例化对象的过程

    子类实例化是否会实例化父类? 不会.父类在子类实例化过程中是并没有被实例化,java中new子类没有实例化父类,只是调用父类的构造方法初始化了,子类从父类继承来的属性,这个调用是子类的对象调用的父类的 ...

  3. 【51nod-1046】最大子矩阵和

    一个M*N的矩阵,找到此矩阵的一个子矩阵,并且这个子矩阵的元素的和是最大的,输出这个最大的值.   例如:3*3的矩阵:   -1 3 -1 2 -1 3 -3 1 2   和最大的子矩阵是:   3 ...

  4. R-一页多图

    https://blog.csdn.net/ailsa__/article/details/45932753

  5. 自定义控件之TagGroup

    转载请注明出处:http://blog.csdn.net/crazy1235/article/details/74907150 标签瀑布流布局! 实现方式有很多种. 继承LinearLayout 继承 ...

  6. VS2017 Product Key

    Enterprise: NJVYC-BMHX2-G77MM-4XJMR-6Q8QF Professional: KBJFW-NXHK6-W4WJM-CRMQB-G3CDH

  7. MYSQL中防止插入重复记录的解决方案(无重复值更新)

    说明:一般我们使用MYSQL插入记录时,类似于这样的语句: insert into table_name(email,phone,user_id) values(‘test9@163.com’,’99 ...

  8. sql_自连接,181,182,196,197

    181. Employees Earning More Than Their Managers https://leetcode.com/problems/employees-earning-more ...

  9. Python错误TypeError: write() argument must be str, not bytes

    2016-07-03 20:51:25 今天使用Python中的pickle存储的时候出现了以下错误: TypeError: write() argument must be str, not byt ...

  10. 洛谷 P3015 [USACO11FEB]最好的括号Best Parenthesis

    传送门 题目大意:给出括号的得分标准. ()得分为1,如果A的得分为S(A),那么 (A)的得分为2*S(A). 题解:搜索 #include<iostream> #include< ...