C++现成的hash函数

原创 2015年11月20日 18:24:39

一、简介

Hash,一般翻译做"散列",也有直接音译为"哈希"的,就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。


二、__gnu_cxx中的hash函数

这个hash函数包含在__gnu_cxx这个命名空间里,实现在backward/hash_fun.h这个头文件里

 inline size_t
  __stl_hash_string(const char* __s)
  {
    unsigned long __h = 0;
    for ( ; *__s; ++__s)
      __h = 5 * __h + *__s;
    return size_t(__h);
  }

然后基于这个hash算法特化了下面几个版本的hash函数

template<> hash<char*>(const char* __s)
template<> hash<const char*>(const char* __s)
template<> hash<char>(char __x)
template<> hash<unsigned char>(unsigned char __x)
template<> hash<signed char>(unsigned char __x)
template<> hash<short>(short __x)
template<> hash<unsigned short>(unsigned short __x)
template<> hash<int>(int __x)
template<> hash<unsigned int>(unsigned int __x)
template<> hash<long>(long __x)
template<> hash<unsigned long>(unsigned long __x)


我也基于这个hash算法实现了一个hash<string>的版本

namespace __gnu_cxx
{
        template <>
        struct hash<string>
        {
                size_t operator()(const string &s) const
                return __stl_hash_string(s.c_str()); }
        };
}


三、tr1中hash函数(Fnv_hash)

特点和用途:FNV能快速hash大量数据并保持较小的冲突率,它的高度分散使它适用于hash一些非常相近的字符串,比如URL,hostname,文件名,text,IP地址等。

这个hash函数包含在std::tr1这个命名空间里,包含tr1/functional头文件即可,实现在tr1_impl/functional_hash.h文件中。下面是它的实现

//Dummy generic implementation (for sizeof(size_t) != 4, 8)
template<std::size_t sizeof(std::size_t)>
struct Fnv_hash
{
  static std::size_t
  hash(const char* first, std::size_t length)
  {
std::size_t result = 0;
for (; length > 0; --length)
  result = (result * 131) + *first++;
return result;
  
};
 
template<>
struct Fnv_hash<4>
{
  static std::size_t
  hash(const char* first, std::size_t length)
  
std::size_t result = static_cast<std::size_t>(2166136261UL);
for (; length > 0; --length)
  
    result ^= (std::size_t)*first++;
    result *= 16777619UL;
  
return result;
  
};
 
template<>
struct Fnv_hash<8>
{
  static std::size_t
  hash(const char* first, std::size_t length)
  {
std::size_t result = static_cast<std::size_t>(14695981039346656037ULL);
for (; length > 0; --length)
  {
    result ^= (std::size_t)*first++;
    result *= 1099511628211ULL;
  }
return result;
  }
};

然后基于这个Fnv_hash算法实现了各种版本的hash函数,其中包括string和wstring版本的。


四、测试

#include <iostream>
#include <string>
#include <tr1/functional>

int main()
{
        std::string name = "jim jim jim";
        //直接调用Fnv_hash
        std::cout << std::tr1::_Fnv_hash<1>::hash(name.c_str(), name.size()) << std::endl;
        std::cout << std::tr1::_Fnv_hash<4>::hash(name.c_str(), name.size()) << std::endl;
        std::cout << std::tr1::_Fnv_hash<8>::hash(name.c_str(), name.size()) << std::endl;
 
        //string
        std::cout << std::tr1::hash<std::string>()(name) << std::endl;
 
        //wstring
        std::wstring age = L"22222";;
        std::cout << std::tr1::hash<std::wstring>()(age) << std::endl;
 
        //bool
        std::cout << std::tr1::hash<bool>()(true) << std::endl;
 
        //float
        std::cout << std::tr1::hash<float>()(24.0f) << std::endl;
 
        //double
        std::cout << std::tr1::hash<double>()(24.0) << std::endl;
 
        //short
        std::cout << std::tr1::hash<short>()(static_cast<short>(24)) << std::endl;
 
        //int
        std::cout << std::tr1::hash<int>()(24) << std::endl;
         
        //long
        std::cout << std::tr1::hash<long>()(24L) << std::endl;
        return 0;
}


说明:

gcc 4.8以上的版本支持c++11,我用的是4.7的版本。tr1/functional在gcc 4.7的版本里gcc的搜寻路径下直接就有functional这个头文件,可以直接#include <functional>,这样就不需要std::tr1这个明明空间了,直接在std的命名空间下,编译的时候需要加个参数即可。

[jim@localhost ~]$g++ -std=c++0x myHash.cpp

c++基础知识,有现成的函数不用,非的自己设计算法,这不是坑爹吗?

那天天气不错,小白(纯属虚构,也许是我,你猜,呵呵)兴高采烈地去xx手机游戏公司面试,带上自己的学历,简历,还有android 手机 手机除了便于联系贵公司之外,最重要的一点,手机上安装有自己制作的...

c++基础知识,有现成的函数不用,非的自己设计算法,这不是坑爹吗?

那天天气不错,小白(纯属虚构,也许是我,你猜,呵呵)兴高采烈地去xx手机游戏公司面试,带上自己的学历,简历,还有android 手机 手机除了便于联系贵公司之外,最重要的一点,手机上安装有自己制作的...

C++中对hash_map自定义哈希函数和比较函数的理解

首先申明一下,我是菜鸟,真正的菜鸟,不是谦虚。所以很多地方有错误,需要大家指出。我只是为了记录,顺便加深自己的理解,不是为了炫耀什么。             这两天学习使用hash_map,在网上...

一个sample学会使用c++比较函数对象和hash函数对象

/* 1、自定义hash函数对象用于unordered_set中 2、自定义Compare函数对象用于排序 3、学习使用优先级队列priority_queue */ #include #inclu...

uthash开源的hash函数实现

  • 2015年09月25日 11:05
  • 11KB
  • 下载

密码Hash函数的碰撞攻击

  • 2015年10月25日 22:14
  • 7.45MB
  • 下载

经典字符串hash函数介绍及性能比较

各种字符串Hash函数 http://www.cnblogs.com/atlantis13579/archive/2010/02/06/1664792.html http://blog.csdn....
  • djinglan
  • djinglan
  • 2013年04月17日 11:08
  • 21242

所有有关HASH函数的论文

  • 2010年05月05日 22:02
  • 4.1MB
  • 下载

hash函数MD5算法源程序

  • 2009年12月21日 10:52
  • 24KB
  • 下载

常见的hash函数 :-D 非常经典!!

常见的Hash算法 2011-04-08 22:31 1999人阅读 评论(6) 收藏 举报 简介哈希方法学哈希函数和素数位偏向各种形式的哈希常用的哈希函数各版本哈希代码下载 ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C++现成的hash函数
举报原因:
原因补充:

(最多只允许输入30个字)