哈希表的ELFhash算法

算法:
   
while(*key)//遍历字符串  
    { h=(h<<4)+*key++;//把h左移4位加上该字符付给h  
    unsigned long g=h&0Xf0000000L;  
    //取h的高四位付给g  
      
    if(g) h^=g>>24;//如果g不为0,让h和g的高八位异或再付给h  
      
    h&=~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)为哈希函数。(注意:这个函数并不一定是数学函数)  

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

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

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

猜你喜欢

转载自renegade24.iteye.com/blog/1299626