Lane's Tech Space

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

  HashTable或者Dictionary是两个我们常用的数据结构。提供了一种键值对应的数据访问方式,其有别于Array采用下标的方式检索数据。了解其内部的实现机制有助于我们写出更优秀的程序。

  .NET中的HashTable(Dictionary将不做详细描述,算法实现于HashTable一样,只是加上了对范形的支持)采用双哈希(二次哈希)的算法。这里对二次哈希作一个简单介绍。在数据结构的课本中,我们知道哈希表是会出现冲突的,而处理冲突的方法有:1、开放地址法,简单的说就是如果出现冲突就找数组中的下一个位置,此方法是最简单的处理冲突的方法;2、再哈希法,就是在同义词产生地址冲突时计算另一个哈希函数地址,直到冲突不再发生,这里需要定义n个哈希函数;3、链地址法,即每一个储存位置都为一个链表;4、建立一个公共溢出区。.NET中的二次哈希是再哈希法的一个简化,其只定义两个哈希函数h1,h2。h1使用的是每个类的GetHashCode方法,h2的定义为:incr = 1+(((seed>>5)+1)%(hashsize-1))),其中,seed为第一次Hash的值,HashSize为整个表的大小。当冲突时,在seed的基础上加incr。如下代码:

uint seed;
            
uint incr;
            
// Assume we only have one thread writing concurrently.  Modify
            
// buckets to contain new data, as long as we insert in the right order.
            uint hashcode = InitHash(key, buckets.Length, out seed, out incr);
            
int  ntry = 0;
            
int emptySlotNumber = -1// We use the empty slot number to cache the first empty slot. We chose to reuse slots
            
// create by remove that have the collision bit set over using up new slots.
            int bucketNumber = (int) (seed % (uint)buckets.Length);
            
do {

                
// 插入操作
                bucketNumber = (int) (((long)bucketNumber + incr)% (uint)buckets.Length);               
            }
 while (++ntry < buckets.Length);


  上面的代码中出现了一个buckets的东西,这正式HashTable中的数据结构。HashTable是有一个定长的bucket数组组成的。
// The hash table data.
        
// This cannot be serialised
        private struct bucket {
            
public Object key;
            
public Object val;
            
public int hash_coll;   // Store hash code; sign bit means there was a collision.
        }

  HashTable中有一个有趣的设计,每一个key的哈希值都被存储在hash_coll中,这个key的长度不超过31位(在Int32的条件下),其最高位用于作冲突检测。当我们增加一条记录的时候,HashTable会首先查看由哈希值对应的bucket数组的下标的bucket是否有冲突,并作相应处理。

  由于时间和兴趣的关系,我没有继续研究HashTable的冲突处理,空元素处理等问题。有兴趣的朋友可以继续研究。

  如何研究.NET的代码?这是一个好问题,我的方法是,如果不需要看算法,并且问题不复杂,可以用Reflector看看Microsoft的.dll,否则,如本文的HashTable(我先是使用Reflector查看,结果看的很累),可以去下载Microsoft Shared Source CLI (SSCLI)(也称Rotor,.NET Code Name),里面有大部分核心类、编译器、运行环境的源代码。

  OK,就写这么多了,如有错误,记得通知我哦!

posted on 2007-05-08 15:04  Lane Zhang  阅读(1105)  评论(0编辑  收藏  举报