上面的说明中存在一个刺眼的缺陷 。当有冲突(两个不同的字符串有相同的哈希值)发生的时候怎么办?显而易见的,它们不能占据哈希表中的同一个位置 。通常的解决办法是为每一个哈希值指向一个链表,用于存放所有哈希冲突的值;
MPQs使用一个存放文件名的哈希表来跟踪文件内部,但是表的格式与通常方法有点不同,首先不像通常的做法使用哈希值作为偏移量,存储实际的文件名 。MPQs 根本不存储文件名,而是使用了三个不同的哈希值:一个用做哈希表偏移量,两个用作核对 。这两个核对的哈希值用于替代文件名 。当然从理论上说存在两个不同的文件名得到相同的三个哈希值,但是这种情况发送的几率是:1:18889465931478580854784,这应该足够安全了 。
MPQ’s的哈希表的实现与传统实现的另一个不同的地方是,相对与传统做法(为每个节点使用一个链表,当冲突发生的时候,遍历链表进行比较),看一下下面的示范代码,在MPQ中定位一个文件进行读操作:
01 . int GetHashTablePos(char *lpszString, MPQHASHTABLE *lpTable, int nTableSize)02 . {03 . const int HASH_OFFSET = 0, HASH_A = 1, HASH_B = 2;04 . int nHash = HashString(lpszString, HASH_OFFSET);05 . int nHashA = HashString(lpszString, HASH_A);06 . int nHashB = HashString(lpszString, HASH_B);07 . int nHashStart = nHash % nTableSize,nHashPos = nHashStart;08 . while (lpTable[nHashPos].bExists)09 . {10 . if (lpTable[nHashPos].nHashA == nHashA && lpTable[nHashPos].nHashB == nHashB)11 . return nHashPos;12 . else13 . nHashPos = (nHashPos + 1) % nTableSize;14 . if (nHashPos == nHashStart)15 . break;16 . }17 . return -1; //Error value18. }无论代码看上去有多么复杂,其背后的理论并不难 。读一个文件的时候基本遵循下面这样一个过程:
- 1. 计算出字符串的三个哈希值(一个用来确定位置,另外两个用来校验)
- 2. 察看哈希表中的这个位置
- 3. 哈希表中这个位置为空吗?如果为空,则肯定该字符串不存在,返回
- 4. 如果存在,则检查其他两个哈希值是否也匹配,如果匹配,则表示找到了该字符串,返回
- 5. 移到下一个位置,如果已经越界,则表示没有找到,返回
- 6. 看看是不是又回到了原来的位置,如果是,则返回没找到
- 7. 回到3
推荐阅读
- 很棒的Mac平台图像处理软件
- 金庸小说中的少林武功 谁是金庸笔下第一高手
- 白鹿茶韵词语茶香与茶友起体验传统文化的魅力
- 青椒炒白虾
- 上海国际茶文化旅游节将探索茶文化合作交流的新模式
- 用优良品种和优良方法制造的湖南茶叶产品决心创新
- 生炝醉虾
- 干锅小黄鱼
- 关于茶或促进糖尿病伤口愈合的研究表明茶多酚在其中发挥作用
- 钱明茶的产量将略微增加
