哈希表的ELFhash算法

来源:互联网 发布:2016网络投资平台 编辑:程序博客网 时间:2024/05/22 08:12
算法:
while(*key)//遍历字符串{ h=(h<<4)+*key++;//把h左移4位加上该字符付给hunsigned long g=h&0Xf0000000L;//取h的高四位付给gif(g) h^=g>>24;//如果g不为0,让h和g的高八位异或再付给hh&=~g;//对g取反并与h相与付给h} return h%MOD; //得到哈希值返回




JAVA版:

public long ELFHash(String str){      long hash = 0;      long x    = 0;       for(int i = 0; i < str.length(); i++)      {         hash = (hash << 4) + str.charAt(i);          if((x = hash & 0xF0000000L) != 0)          {             hash ^= (x >> 24);        }         hash &= ~x;      }       return hash; }


C版:

    unsigned int ELFHash(char* str, unsigned int len)      {         unsigned int hash = 0;         unsigned int x    = 0;         unsigned int i    = 0;                for(i = 0; i < len; str++, i++)         {            hash = (hash << 4) + (*str);         if((x = hash & 0xF0000000L) != 0)         {hash ^= (x >> 24);            }            hash &= ~x;         }                return hash;      }  


C++版:

unsigned int ELFHash(const std::string& str)  {     unsigned int hash = 0;     unsigned int x    = 0;        for(std::size_t i = 0; i < str.length(); i++)     {    hash = (hash << 4) + str[i];         if((x = hash & 0xF0000000L) != 0)         {          hash ^= (x >> 24);    }    hash &= ~x;     }        return hash;  } 


实际应用

  以上就是一些关于hash以及其相关的一些基本预备知识。那么在emule里面他具体起到什么作用呢?  

        大家都知道emule是基于P2P (Peer-to-peer的缩写,指的是点对点的意思的软件),它采用了"多源文件传输协议”(MFTP,the Multisource FileTransferProtocol)。在协议中,定义了一系列传输、压缩和打包还有积分的标准,emule对于每个文件都有md5-hash的算法设置,这使得该文件独一无二,并且在整个网络上都可以追踪得到。  

         什么是文件的hash值呢?  

         MD5-Hash-文件的数字文摘通过Hash函数计算得到。不管文件长度如何,它的Hash函数计算结果是一个固定长度的数字。与加密算法不同,这一个Hash算法是一个不可逆的单向函数。采用安全性高的Hash算法,如MD5、SHA时,两个不同的文件几乎不可能得到相同的Hash结果。因此,一旦文件被修改,就可检测出来。  

         当我们的文件放到emule里面进行共享发布的时候,emule会根据hash算法自动生成这个文件的hash值,他就是这个文件唯一的身份标志,它包含了这个文件的基本信息,然后把它提交到所连接的服务器。当有他人想对这个文件提出下载请求的时候,这个hash值可以让他人知道他正在下载的文件是不是就是他所想要的。尤其是在文件的其他属性被更改之后(如名称等)这个值就更显得重要。而且服务器还提供了,这个文件当前所在的用户的地址,端口等信息,这样emule就知道到哪里去下载了。  

           一般来讲我们要搜索一个文件,emule在得到了这个信息后,会向被添加的服务器发出请求,要求得到有相同hash值的文件。而服务器则返回持有这个文件的用户信息。这样我们的客户端就可以直接的和拥有那个文件的用户沟通,看看是不是可以从他那里下载所需的文件。  

           对于emule中文件的hash值是固定的,也是唯一的,它就相当于这个文件的信息摘要,无论这个文件在谁的机器上,他的hash值都是不变的,无论过了多长时间,这个值始终如一,当我们在进行文件的下载上传过程中,emule都是通过这个值来确定文件。  

           那么什么是userhash呢?  

           道理同上,当我们在第一次使用emule的时候,emule会自动生成一个值,这个值也是唯一的,它是我们在emule世界里面的标志,只要你不卸载,不删除config,你的userhash值也就永远不变,积分制度就是通过这个值在起作用,emule里面的积分保存,身份识别,都是使用这个值,而和你的id和你的用户名无关,你随便怎么改这些东西,你的userhash值都是不变的,这也充分保证了公平性。其实他也是一个信息摘要,只不过保存的不是文件信息,而是我们每个人的信息。  

哈希表不可避免冲突(collision)现象:对不同的关键字可能得到同一哈希地址即key1≠key2,而hash(key1)=hash(key2)。具有相同函数值的关键字对该哈希函数来说称为同义词(synonym)。因此,在建造哈希表时不仅要设定一个好的哈希函数,而且要设定一种处理冲突的方法。可如下描述哈希表:根据设定的哈希函数H(key)和所选中的处理冲突的方法,将一组关键字映象到一个有限的、地址连续的地址集(区间)上并以关键字在地址集中的“象”作为相应记录在表中的存储位置,这种表被称为哈希表。  对于动态查找表而言,1)表长不确定;2)在设计查找表时,只知道关键字所属范围,而不知道确切的关键字。因此,一般情况需建立一个函数关系,以f(key)作为关键字为key的录在表中的位置,通常称这个函数f(key)为哈希函数。(注意:这个函数并不一定是数学函数)  

           哈希函数是一个映象,即:将关键字的集合映射到某个地址集合上,它的设置很灵活,只要这个地址集合的大小不超出允许范围即可。

           现实中哈希函数是需要构造的,并且构造的好才能使用的好。 

用途:加密,解决冲突问题。。。。  用途很广,比特精灵中就使用了哈希函数,你可 以自己看看。  具体可以学习一下数据结构和算法的书。