青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

posts - 126,  comments - 73,  trackbacks - 0

先提一個簡單的問題,如果有一個龐大的字符串?dāng)?shù)組,然后給你一個單獨(dú)的字符串,讓你從這個數(shù)組中查找是否有這個字符串并找到它,你會怎么做?

有一個方法最簡單,老老實(shí)實(shí)從頭查到尾,一個一個比較,直到找到為止,我想只要學(xué)過程序設(shè)計(jì)的人都能把這樣一個程序作出來,但要是有程序員把這樣的程序交給用戶,我只能用無語來評價,或許它真的能工作,但...也只能如此了。

最合適的算法自然是使用HashTable(哈希表),先介紹介紹其中的基本知識,所謂Hash,一般是一個整數(shù),通過某種算法,可以把一個字符串"壓縮" 成一個整數(shù),這個數(shù)稱為Hash,當(dāng)然,無論如何,一個32位整數(shù)是無法對應(yīng)回一個字符串的,但在程序中,兩個字符串計(jì)算出的Hash值相等的可能非常小,下面看看在MPQ中的Hash算法

unsigned long HashString(char *lpszFileName, unsigned long dwHashType)
{
unsigned char *key = (unsigned char *)lpszFileName;
unsigned long seed1 = 0x7FED7FED, seed2 = 0xEEEEEEEE;
int ch;

while(*key != 0)
{
??ch = toupper(*key++);

seed1 = cryptTable[(dwHashType << 8) + ch] ^ (seed1 + seed2);
seed2 = ch + seed1 + seed2 + (seed2 << 5) + 3;
}
return seed1;
}

Blizzard的這個算法是非常高效的,被稱為"One-Way Hash",舉個例子,字符串"unitneutralacritter.grp"通過這個算法得到的結(jié)果是0xA26067F3。
是不是把第一個算法改進(jìn)一下,改成逐個比較字符串的Hash值就可以了呢,答案是,遠(yuǎn)遠(yuǎn)不夠,要想得到最快的算法,就不能進(jìn)行逐個的比較,通常是構(gòu)造一個哈希表(Hash Table)來解決問題,哈希表是一個大數(shù)組,這個數(shù)組的容量根據(jù)程序的要求來定義,例如1024,每一個Hash值通過取模運(yùn)算 (mod)對應(yīng)到數(shù)組中的一個位置,這樣,只要比較這個字符串的哈希值對應(yīng)的位置又沒有被占用,就可以得到最后的結(jié)果了,想想這是什么速度?是的,是最快的O(1),現(xiàn)在仔細(xì)看看這個算法吧
int GetHashTablePos(char *lpszString, SOMESTRUCTURE *lpTable, int nTableSize)
{
int nHash = HashString(lpszString), nHashPos = nHash % nTableSize;

if (lpTable[nHashPos].bExists && !strcmp(lpTable[nHashPos].pString, lpszString))
??return nHashPos;
else
??return -1; //Error value
}

看到此,我想大家都在想一個很嚴(yán)重的問題:"如果兩個字符串在哈希表中對應(yīng)的位置相同怎么辦?",畢竟一個數(shù)組容量是有限的,這種可能性很大。解決該問題的方法很多,我首先想到的就是用"鏈表",感謝大學(xué)里學(xué)的數(shù)據(jù)結(jié)構(gòu)教會了這個百試百靈的法寶,我遇到的很多算法都可以轉(zhuǎn)化成鏈表來解決,只要在哈希表的每個入口掛一個鏈表,保存所有對應(yīng)的字符串就OK了。

事情到此似乎有了完美的結(jié)局,如果是把問題獨(dú)自交給我解決,此時我可能就要開始定義數(shù)據(jù)結(jié)構(gòu)然后寫代碼了。然而Blizzard的程序員使用的方法則是更精妙的方法。基本原理就是:他們在哈希表中不是用一個哈希值而是用三個哈希值來校驗(yàn)字符串。

中國有句古話"再一再二不能再三再四",看來Blizzard也深得此話的精髓,如果說兩個不同的字符串經(jīng)過一個哈希算法得到的入口點(diǎn)一致有可能,但用三個不同的哈希算法算出的入口點(diǎn)都一致,那幾乎可以肯定是不可能的事了,這個幾率是1:18889465931478580854784,大概是10的 22.3次方分之一,對一個游戲程序來說足夠安全了。

現(xiàn)在再回到數(shù)據(jù)結(jié)構(gòu)上,Blizzard使用的哈希表沒有使用鏈表,而采用"順延"的方式來解決問題,看看這個算法:
int GetHashTablePos(char *lpszString, MPQHASHTABLE *lpTable, int nTableSize)
{
const int HASH_OFFSET = 0, HASH_A = 1, HASH_B = 2;
int nHash = HashString(lpszString, HASH_OFFSET);
int nHashA = HashString(lpszString, HASH_A);
int nHashB = HashString(lpszString, HASH_B);
int nHashStart = nHash % nTableSize, nHashPos = nHashStart;

while (lpTable[nHashPos].bExists)
{
??if (lpTable[nHashPos].nHashA == nHashA && lpTable[nHashPos].nHashB == nHashB)
?? return nHashPos;
??else
?? nHashPos = (nHashPos + 1) % nTableSize;
??
??if (nHashPos == nHashStart)
?? break;
}

return -1; //Error value
}

1. 計(jì)算出字符串的三個哈希值(一個用來確定位置,另外兩個用來校驗(yàn))
2. 察看哈希表中的這個位置
3. 哈希表中這個位置為空嗎?如果為空,則肯定該字符串不存在,返回
4. 如果存在,則檢查其他兩個哈希值是否也匹配,如果匹配,則表示找到了該字符串,返回
5. 移到下一個位置,如果已經(jīng)越界,則表示沒有找到,返回
6. 看看是不是又回到了原來的位置,如果是,則返回沒找到
7. 回到3

怎么樣,很簡單的算法吧,但確實(shí)是天才的idea, 其實(shí)最優(yōu)秀的算法往往是簡單有效的算法。

http://blog.blogchina.com/article_85296.361466.html

posted on 2007-08-21 11:51 我風(fēng) 閱讀(6974) 評論(8)  編輯 收藏 引用

FeedBack:
# re: 打造最快的Hash表(轉(zhuǎn))
2007-11-03 01:07 | wo
不是很懂,"從這個數(shù)組中查找是否有這個字符串并找到它",和這怎么聯(lián)系上的?謝謝  回復(fù)  更多評論
  
# re: 打造最快的Hash表(轉(zhuǎn))
2007-12-05 17:07 | 祁祁
果然精妙  回復(fù)  更多評論
  
# re: 打造最快的Hash表(轉(zhuǎn))
2009-03-25 17:03 | akore
無聊, 跟在字符串?dāng)?shù)組中找到目標(biāo)字符串有個屁聯(lián)系!  回復(fù)  更多評論
  
# re: 打造最快的Hash表(轉(zhuǎn))
2009-04-21 14:41 | brightcoder
跟你提的問題有什么關(guān)聯(lián)  回復(fù)  更多評論
  
# re: 打造最快的Hash表(轉(zhuǎn))[未登錄]
2009-05-22 00:41 | joe
@akore
對你相當(dāng)無語..先看懂再說吧  回復(fù)  更多評論
  
# re: 打造最快的Hash表(轉(zhuǎn))
2009-09-01 13:59 | charrie
頂,最后三個哈希值的還沒有太明白,前面的正是我需要的,謝謝樓主!  回復(fù)  更多評論
  
# re: 打造最快的Hash表(轉(zhuǎn))
2009-10-12 16:32 | river
如果只進(jìn)行一次這樣的查找操作,那么順序查找,當(dāng)然是唯一選擇;
你說的高效,是針對要進(jìn)行無數(shù)次這樣在同一個長串中查找子串的操作的情況,對吧?道理是很簡單,確實(shí)還不錯。
你這個文章,意思沒有表達(dá)的很清楚,怨不得別人提出質(zhì)疑;
同時,題目為“打造最快的hash表”,我不太認(rèn)同。  回復(fù)  更多評論
  
# re: 打造最快的Hash表(轉(zhuǎn))
2009-10-13 23:17 | Veiir
@river
Hash表的目的是讓搜索時間穩(wěn)定在一個數(shù)字上。

比如有幾百個模型包,要依靠名稱取其中一個,那么如果你逐個比較文件名篩選,如果是這個文件名是a開頭還好,萬一是z開頭呢?會不會花費(fèi)的時間很長?那么你這個游戲畫面的載入時間豈不是很不穩(wěn)定?

如果把這些模型包通過文件名hash運(yùn)算得出來一個數(shù)字,比如20,放到同一個數(shù)組array的這個數(shù)字的位置array[20],那么以后要讀取這個模型包,僅用知道文件名,通過hash運(yùn)算得出同樣的數(shù)字20,那么你可以直接去取數(shù)組array的這個數(shù)字位置就好了array[20]。那么你只用了一個hash運(yùn)算,這個運(yùn)算所花費(fèi)的時間是一定的,要比不知道做多少次文件名比較花的時間短多了,取址當(dāng)然是很快的,那么你游戲畫面載入時間就不會很長,也比較穩(wěn)定.  回復(fù)  更多評論
  

只有注冊用戶登錄后才能發(fā)表評論。
網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


<2012年10月>
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910

常用鏈接

留言簿(12)

隨筆分類

隨筆檔案

文章檔案

相冊

收藏夾

C++

MyFavorite

搜索

  •  

積分與排名

  • 積分 - 328337
  • 排名 - 75

最新評論

閱讀排行榜

評論排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            99精品国产高清一区二区| 久久偷看各类wc女厕嘘嘘偷窃| 欧美成人免费观看| 久久精品伊人| 午夜在线精品| 国产一区二区精品丝袜| 欧美一区二区视频在线观看| 中文一区在线| 黄色亚洲免费| 亚洲娇小video精品| 欧美日韩亚洲一区二区三区四区| 亚洲一区三区视频在线观看| 香蕉成人久久| 亚洲精选久久| 亚洲一级特黄| 亚洲国产日韩美| 亚洲视频一区二区免费在线观看| 亚洲一区二区三区视频| 国产在线精品自拍| 欧美激情一区二区三区四区| 久久午夜精品| 日韩午夜中文字幕| 国产一区二区三区日韩欧美| 欧美高清视频在线观看| 欧美视频免费| 免费看亚洲片| 国产精品h在线观看| 久久资源av| 欧美午夜不卡影院在线观看完整版免费| 亚洲欧美欧美一区二区三区| 久久精品123| 亚洲男人的天堂在线aⅴ视频| 久久久精品国产一区二区三区| 夜夜嗨av一区二区三区网站四季av| 亚洲欧美日韩直播| 亚洲免费观看高清完整版在线观看| 欧美亚洲视频一区二区| 一本色道久久88综合日韩精品| 欧美中文字幕在线播放| 中文在线不卡| 欧美激情中文字幕在线| 久久亚洲私人国产精品va| 欧美午夜精品理论片a级按摩| 欧美大片在线观看一区二区| 国产欧美日韩精品在线| 日韩一区二区精品在线观看| 亚洲国产小视频| 欧美一区二区三区四区视频| 亚洲男人的天堂在线观看| 欧美精品一区三区在线观看| 欧美成人69| 经典三级久久| 久久精品主播| 久久国内精品视频| 国产伦精品一区二区三区四区免费| 亚洲人成欧美中文字幕| 亚洲国产日韩精品| 免费欧美在线视频| 欧美阿v一级看视频| 永久域名在线精品| 久久久国产一区二区三区| 久久久亚洲人| 红桃视频国产精品| 亚洲欧美国产三级| 亚洲美女av电影| 欧美一区二区三区视频在线| 亚洲国产合集| 一区二区三区在线观看欧美| 欧美一区二区福利在线| 久久久久.com| 国内伊人久久久久久网站视频 | 亚洲性av在线| 欧美日韩一本到| 日韩视频在线播放| 亚洲一二三区在线| 国产麻豆午夜三级精品| 午夜激情亚洲| 免费欧美高清视频| 亚洲精品一区二区网址| 亚洲激情小视频| 99av国产精品欲麻豆| 欧美四级在线观看| 亚洲激情校园春色| 久久久一本精品99久久精品66| 久久综合久久综合九色| 亚洲福利久久| 欧美乱妇高清无乱码| 在线视频精品一区| 久久人人97超碰精品888| 亚洲高清中文字幕| 欧美日韩视频在线一区二区| 亚洲欧美一级二级三级| 噜噜噜91成人网| 一区二区欧美日韩视频| 国产日韩在线看| 欧美成人中文字幕在线| 亚洲一区二区三区国产| 农村妇女精品| 午夜视频在线观看一区二区| 极品日韩久久| 欧美亚洲成人精品| 久久久久久自在自线| 99一区二区| 美女图片一区二区| 亚洲在线免费视频| 亚洲国产精品一区二区第四页av| 欧美天天影院| 蜜臀久久久99精品久久久久久| 一区二区精品在线观看| 欧美成人高清视频| 久久精品国产久精国产思思| 亚洲乱码久久| 在线观看日韩国产| 国产精品日韩一区| 欧美激情视频一区二区三区在线播放 | 欧美高清视频一区二区三区在线观看| 亚洲一区二区av电影| 亚洲国产美女| 狠狠入ady亚洲精品| 欧美日韩亚洲综合一区| 欧美承认网站| 久久蜜桃资源一区二区老牛| 亚洲午夜日本在线观看| 亚洲精品在线免费观看视频| 欧美va天堂va视频va在线| 久久国产色av| 欧美一区二区三区四区夜夜大片| 一区二区欧美精品| 99riav国产精品| 日韩午夜激情电影| 91久久精品www人人做人人爽| 国产资源精品在线观看| 国产伦精品一区二区三区四区免费 | 久久精品国产99精品国产亚洲性色| 一区二区三区国产盗摄| 亚洲精品国产无天堂网2021| 亚洲第一天堂av| 一区国产精品| 在线免费不卡视频| ●精品国产综合乱码久久久久| 精品成人一区二区三区| 国产综合18久久久久久| 国产一区二区三区av电影| 国产视频一区二区三区在线观看| 午夜一区二区三区在线观看| 午夜国产精品影院在线观看| 午夜日本精品| 性色av香蕉一区二区| 性欧美大战久久久久久久免费观看| 亚洲欧美自拍偷拍| 久久www成人_看片免费不卡| 欧美影片第一页| 久久人体大胆视频| 欧美高清在线视频观看不卡| 欧美精品亚洲精品| 国产精品国产福利国产秒拍| 国产精品视频久久一区| 国产一区白浆| 亚洲国产欧美不卡在线观看| 日韩视频免费看| 亚洲主播在线| 久久在线视频| 亚洲黄一区二区| 亚洲一二三区视频在线观看| 性欧美暴力猛交69hd| 老司机免费视频一区二区三区| 欧美极品在线观看| 国产酒店精品激情| 在线日韩视频| 亚洲小说欧美另类社区| 久久综合久久综合久久综合| 亚洲国产成人在线播放| 在线综合欧美| 久久久久久9| 欧美色综合天天久久综合精品| 国产午夜精品全部视频播放| 最新日韩精品| 欧美一级午夜免费电影| 欧美激情视频免费观看| 亚洲视屏在线播放| 久久视频一区二区| 国产精品麻豆va在线播放| 尤物视频一区二区| 先锋影音国产一区| 亚洲国产综合在线看不卡| 午夜视频精品| 欧美日韩国产片| 在线成人激情黄色| 亚洲一区二区综合| 亚洲国产精品一区制服丝袜| 亚洲欧美视频在线观看视频| 欧美巨乳波霸| 亚洲国产成人av好男人在线观看| 午夜精品国产精品大乳美女| 亚洲国产精品999| 欧美在线免费一级片| 欧美香蕉视频| 99视频在线观看一区三区| 免费av成人在线| 欧美亚洲视频在线观看|