hash表的实现

方法一:类似STL中hashtable的实现:

摘录自《STL源码剖析》5.7.7节

hashtable以质数来设计表格大小,预先计算好了28个质数,大约都是两倍的关系递增,查询28个质数中,“最接近且大于元素数目”的数字作为vector的长度,如果需要重新分配,则分配下一个质数长度的vector。Bucket所维护的linked list不采用STL的list或者slist(直接指针操作),而至于bucket则使用vector来完成。

开链法处理冲突;

对字符串类似的hash函数的计算如下:

hash(char *s)

{

unsigned long h=0;

for( ; *s ; ++s)

h=5*h+*s;

return size_t(h);

}

对于int,long型,hash函数直接返回

hashable实现容器对比:

hash_set:与set的用法一样,底层是hashtable实现,默认vector大小是100,唯一不同是不排序。
hash_map:与map的用法一样,底层是hashtable实现,默认vector大小是100,唯一不同是不排序。
hash_multimap:与multimap的用法一样,底层是hashtable实现,默认vector大小是100,唯一不同是不排序。
hash_multiset:与multiset的用法一样,底层是hashtable实现,默认vector大小是100,唯一不同是不排序。

方法二:出自陈皓博客《哈希表心得》,

链接:http://blog.csdn.net/haoel/article/details/2863

hash表的组织方式和处理冲突的方法和STL相同,不同的是:

(1)哈希表尺寸的变化方式

下面的数库是哈希表变化尺寸时尺寸大小的一个列表。

static int prime_array[] = {
    17,             /* 0 */
    37,             /* 1 */
    79,             /* 2 */
    163,            /* 3 */
    331,            /* 4 */
    673,            /* 5 */
    1361,           /* 6 */
    2729,           /* 7 */
    5471,           /* 8 */
    10949,          /* 9 */
    21911,          /* 10 */
    43853,          /* 11 */
    87719,          /* 12 */
    175447,         /* 13 */
    350899,         /* 14 */
    701819,         /* 15 */
    1403641,        /* 16 */
    2807303,        /* 17 */
    5614657,        /* 18 */
    11229331,       /* 19 */
    22458671,       /* 20 */
    44917381,       /* 21 */
    89834777,       /* 22 */
    179669557,      /* 23 */
    359339171,      /* 24 */
    718678369,      /* 25 */
    1437356741,     /* 26 */
    2147483647      /* 27 (largest signed int prime) */
};               

#define PRIME_ARRAY_SIZE  (28)

STL中采用的是:

  1. static const int __stl_num_primes = 28;  
  2. static const unsigned long __stl_prime_list[__stl_num_primes] =  
  3. {  
  4.   53,         97,           193,         389,       769,  
  5.   1543,       3079,         6151,        12289,     24593,  
  6.   49157,      98317,        196613,      393241,    786433,  
  7.   1572869,    3145739,      6291469,     12582917,  25165843,  
  8.   50331653,   100663319,    201326611,   402653189, 805306457,  
  9.   1610612741, 3221225473ul, 4294967291ul  
  10. };  
(2)hash函数对字符串的计算:

static unsigned int
getHashIndex(hTab *tabPtr, const char *key)
{
    unsigned int ha = 0;
   
    while (*key)
        ha = (ha * 128 + *key++) % tabPtr->size;

    return ha;

}

(其中key是一个字符串,hTab就是一个哈希表结构, tabPtr->size是哈希表数组的大小)

补充内容:摘录自《Boost程序库探秘——深度解析C++准标准库》第4章

BOOST库中的hash函数是对STL的hash函数的扩充。

stl:仅对char *,char,short,long,int等类型处理,对string,double,float,用户必须自定义哈希函数。

而boost库则增加了:

(1)对stl不支持的类型,如float/double/string/和vector/list等标准容器

(2)还可以对自定义类型计算哈希值

步骤:

1, 成员函数定义hash_value()函数

2, 外部实现重载的自由函数hash_value()函数

  hash表的实现_第1张图片

     hash表的实现_第2张图片

(3)利用hash_combine(),hash_range()组合散列值

       例如:要求对类demo_class的散列值的计算方式是用0作为seed(注seed可为任意值),然后逆序计算v中的所有元素。

         hash表的实现_第3张图片

  

你可能感兴趣的:(hash表的实现)