迷你5207专属论坛

注册

 

发新话题 回复该主题

[计算机常识] [转]什么是哈希表和哈希函数 [复制链接]

发表者
来源:http://blog.sina.com.cn/u/53be98cf010000c4 1 基本原理   我们使用一个下标范围比较大的数组来存储元素。可以设计一个函数(哈希函数, 也叫做散列函数),使得每个元素的关键字都与一个函数值(即数组下标)相对应,于是用这个数组单元来存储这个元素;也可以简单的理解为,按照关键字为每一个元素"分类",然后将这个元素存储在相应"类"所对应的地方。   但是,不能够保证每个元素的关键字与函数值是一一对应的,因此极有可能出现对于不同的元素,却计算出了相同的函数值,这样就产生了"冲突",换句话说,就是把不同的元素分在了相同的"类"之中。后面我们将看到一种解决"冲突"的简便做法。   总的来说,"直接定址"与"解决冲突"是哈希表的两大特点。 2 函数构造   构造函数的常用方法(下面为了叙述简洁,设 h(k) 表示关键字为 k 的元素所对应的函数值):   a) 除余法:   选择一个适当的正整数 p ,令 h(k ) = k mod p   这里, p 如果选取的是比较大的素数,效果比较好。而且此法非常容易实现,因此是最常用的方法。   b) 数字选择法:   如果关键字的位数比较多,超过长整型范围而无法直接运算,可以选择其中数字分布比较均匀的若干位,所组成的新的值作为关键字或者直接作为函数值。 3 冲突处理   线性重新散列技术易于实现且可以较好的达到目的。令数组元素个数为 S ,则当 h(k) 已经存储了元素的时候,依次探查 (h(k)+i) mod S , i=1,2,3…… ,直到找到空的存储单元为止(或者从头到尾扫描一圈仍未发现空单元,这就是哈希表已经满了,发生了错误。当然这是可以通过扩大数组范围避免的)。 4 支持运算   哈希表支持的运算主要有:初始化(makenull)、哈希函数值的运算(h(x))、插入元素(insert)、查找元素(member)。   设插入的元素的关键字为 x ,A 为存储的数组。   初始化比较容易,例如
  1.   const empty=maxlongint; // 用非常大的整数代表这个位置没有存储元素
  2.      p=9997;      // 表的大小
  3.   procedure makenull;
  4.    var i:integer;
  5.    begin
  6.     for i:=0 to p-1 do
  7.      A[i]:=empty;
  8.    End;
复制代码
哈希函数值的运算根据函数的不同而变化,例如除余法的一个例子:
  1.   function h(x:longint):Integer;
  2.    begin
  3.     h:= x mod p;
  4.    end;
复制代码
我们注意到,插入和查找首先都需要对这个元素定位,即如果这个元素若存在,它应该存储在什么位置,因此加入一个定位的函数 locate

  1.   function locate(x:longint):integer;
  2.    var orig,i:integer;
  3.    begin
  4.     orig:=h(x);
  5.     i:=0;
  6.     while (i<S)and(A[(orig+i)mod S]<>x)and(A[(orig+i)mod S]<>empty) do
  7.      inc(i);
  8.      //当这个循环停下来时,要么找到一个空的存储单元,要么找到这个元
  9.      //素存储的单元,要么表已经满了
  10.     locate:=(orig+i) mod S;
  11.    end;
  12.   插入元素
  13.   procedure insert(x:longint);
  14.    var posi:integer;
  15.    begin
  16.     posi:=locate(x);      //定位函数的返回值
  17.     if A[posi]=empty then A[posi]:=x
  18.           else error; //error 即为发生了错误,当然这是可以避免的
  19.    end;
复制代码
查找元素是否已经在表中
  1.   procedure member(x:longint):boolean;
  2.     var posi:integer;
  3.     begin
  4.      posi:=locate(x);
  5.      if A[posi]=x then member:=true
  6.              else member:=false;
  7.     end;
复制代码
这些就是建立在哈希表上的常用基本运算。
本主题由 管理员 5207 于 2007-12-2 11:29:20 执行 主题分类 操作
分享 转发
相信与不相信都是矛盾的.  5207宣!欢迎您来到点滴论坛
TOP
沙发

回复: [转]什么是哈希表和哈希函数

一个简单的应用例子:转:http://www.binarytimes.cn/simple/index.php?t166.html 对于动态查找表而言,1) 表长不确定;2)在设计查找表时,只知道关键字所属范围,而不知道确切的关键字。因此,一般情况需建立一个函数关系,以f(key)作为关键字为key的录在表中的位置,通常称这个函数f(key)为哈希函数。(注意:这个函数并不一定是数学函数) 哈希函数是一个映象,即:将关键字的集合映射到某个地址集合上,它的设置很灵活,只要这个地址集合的大小不超出允许范围即可。 现实中哈希函数是需要构造的,并且构造的好才能使用的好。 用途:加密,解决冲突问题。。。。 用途很广,比特精灵中就使用了哈希函数,你可 以自己看看。 具体可以学习一下数据结构和算法的书。 [/td][/tr]
[tr=#ffffff]
cat2007-03-30 16:45
▲散列表(也叫哈希表),是根据关键码值直接进行访问的数据结构,也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。 ▲我举个c#的例子吧:
  1. //定义字典
  2. Hashtable myHT = new Hashtable();
  3. myHT.Add( "我", "Me" );
  4. myHT.Add( "你", "You" );
  5. myHT.Add( "他", "He" );


  6. //查找字典

  7. if(myHT.ContainsKey("我"))
  8. {
  9. return myHT["我"].ToString(); //返回 "Me"
复制代码
[tr=#ffffff]
cat2007-03-30 16:46
散列。 MD5加密算法用的就是散列技术了。 对一个值进行放大,然后取其中的一部分。 比如:我的散列算法是扩大5次方,重复1次(也就是进行2次扩大)。然后取其中的第2位之第5位。 输入2,扩大5次方,重复3次。(2^5)^5=33554432。然后取其中的第2位到第5位。也就是5443。5443就是散列值了。
相信与不相信都是矛盾的.  5207宣!欢迎您来到点滴论坛
TOP
发新话题 回复该主题