標(biāo)題: hash [打印本頁]
作者: 51黑tt 時間: 2016-3-5 23:41
標(biāo)題: hash
HashMap、Map等是很多公司面試、筆試的時候常考的題目,也是實際開發(fā)中經(jīng)常用到的數(shù)據(jù)結(jié)構(gòu),必須好好掌握。因此我從《J2EE開發(fā)全程實錄》中摘取了下面的片段,希望對同學(xué)們有幫助。學(xué)習(xí)時請對照著《數(shù)據(jù)結(jié)構(gòu)》這門課中“散列”相關(guān)的章節(jié)復(fù)習(xí)。
在實際問題中,按照給定的值進行數(shù)據(jù)查詢是經(jīng)常遇到的,比如,在電話號碼簿中查詢某個人的電話號碼;在圖書館中按照ISBN 編號查找某本書的位置;在地圖中按照坐標(biāo)查找某個地點的地名等等。為此,人們創(chuàng)造了一種能夠根據(jù)記錄的關(guān)鍵碼 ( 也就是用以標(biāo)識數(shù)據(jù)在記錄中的存放位置的數(shù)據(jù)項 ) 方便的檢索到對應(yīng)的記錄信息的數(shù)據(jù)結(jié)構(gòu),這就是字典 ( Dictionary ) 。
2.2.1字典的定義我們都使用過字典,如英漢字典、成語字典,圖書的檢索目錄、電話簿等也可以看作廣義上的字典。在計算機科學(xué)中,把字典也當(dāng)成一種數(shù)據(jù)結(jié)構(gòu)。
我們把字典定義為“鍵- 值對” (Key-Value Pair) 的集合。根據(jù)不同的問題,我們?yōu)槊趾椭蒂x予不同的含義,比如,在英漢字典中,英文單詞是名字,此單詞的中文解釋條目是值;在電話簿中,人名是名字,此人名對應(yīng)的電話號碼是值。
字典最基本的操作包括:find( 查找 ) 、 add( 插入 ) 、 remove( 刪除 ) ,分別用來從字典中檢索數(shù)據(jù)、插入數(shù)據(jù)和刪除數(shù)據(jù)。在實際存儲中,我們將“鍵 - 值對”存儲于記錄中,通過鍵 ( 也就是“鍵 - 值對”中的名字 ) 來標(biāo)識該“鍵 - 值對”。“鍵 - 值對”的存放位置和其鍵之間的對應(yīng)關(guān)系用一個二元組表示: ( 鍵 , 值的位置 ) 。
從字典中查找“鍵- 值對”的最簡單方法就是使用數(shù)組存儲,然后在查找的時候遍歷此數(shù)組,當(dāng)遍歷到和被查找的“鍵 - 值對”的名字相同項的時候,這個“鍵 - 值對”就被找到了。這種最樸實的方式肯定是不能滿足實際要求的,因此人們發(fā)明了一種檢索效率非常高的組織字典數(shù)據(jù)的方法 ,即哈希表結(jié)構(gòu)。
2.2.2哈希表與哈希方法哈希方法在“鍵- 值對”的存儲位置與它的鍵之間建立一個確定的對應(yīng)函數(shù)關(guān)系 hash() ,使得每一個鍵與結(jié)構(gòu)中的一個唯一的存儲位置相對應(yīng):
存儲位置=hash( 鍵 )
在搜索時,首先對鍵進行hash 運算,把求得的值當(dāng)做“鍵 - 值對”的存儲位置,在結(jié)構(gòu)中按照此位置取“鍵 - 值對”進行比較,若鍵相等,則表示搜索成功。在存儲“鍵 - 值對”的時候,依照相同的 hash 函數(shù)計算存儲位置,并按此位置存放,這種方法就叫做哈希方法,也叫做散列方法。在哈希方法中使用的轉(zhuǎn)換函數(shù) hash 被稱作哈希函數(shù) ( 或者散列函數(shù) ) 。按照此中算法構(gòu)造出來的表叫做哈希表 ( 或者散列表 ) 。
哈希函數(shù)建立了從“鍵- 值對”到哈希表地址集合的一個映射,有了哈希函數(shù),我們就可以根據(jù)鍵來確定“鍵 - 值對”在哈希表中的位置的地址。使用這種方法由于不必進行多次鍵的比較,所以其搜索速度非常快,很多系統(tǒng)都使用這種方法進行數(shù)據(jù)的組織和檢索。
舉一個例子,有一組“鍵值對”:<5, ” tom ” >、 <8, ” Jane ” >、 <12, ” Bit ” >、 <17, ” Lily ” >、 <20, ” sunny ” >,我們按照如下哈希函數(shù)對鍵進行計算 :hash(x)=x%17+3 ,得出如下結(jié)果: hash(5)=8 、 hash(8)=11 、 hash(12)=15 、 hash(17)=3 、 hash(20)=6 。我們把 <5, ” tom ” >、 <8, ” Jane ” >、 <12, ” Bit ” >、 <17, ” Lily ” >、 <20, ” sunny ” >分別放到地址為 8 、 11 、 15 、 3 、 6 的位置上。當(dāng)要檢索 17 對應(yīng)的值的時候,只要首先計算 17 的哈希值為 3 ,然后到地址為 3 的地方去取數(shù)據(jù)就可以找到 17 對應(yīng)的數(shù)據(jù)是“ Lily ”了,可見檢索速度是非常快的。
2.2.3沖突與沖突的解決通常鍵的取值范圍比哈希表地址集合大很多,因此有可能經(jīng)過同一哈希函數(shù)的計算,把不同的鍵映射到了同一個地址上面,這就叫沖突。比如,有一組“鍵- 值對”,其鍵分別為 12361 、 7251 、 3309 、 30976 ,采用的哈希函數(shù)是:
public static int hash(int key)
{
return key%73+13420;
}
則將會得到hash(12361)=hash(7251)=hash(3309)=hash(30976)=13444 ,即不同的鍵通過哈希函數(shù)對應(yīng)到了同一個地址,我們稱這種哈希計算結(jié)果相同的不同鍵為同義詞。
如果“鍵- 值 對”在加入哈希表的時候產(chǎn)生了沖突,就必須找另外一個地方來存放它,沖突太多會降低數(shù)據(jù)插入和搜索的效率,因此希望能找到一個不容易產(chǎn)生沖突的函數(shù),即構(gòu) 造一個地址分布比較均勻的哈希函數(shù)。常用的哈希函數(shù)包括:直接定址法、數(shù)字分析法、除留余數(shù)法、乘留余數(shù)法、平方取中法、折疊法等。應(yīng)該根據(jù)實際工作中關(guān) 鍵碼的特點選用適當(dāng)?shù)姆椒ā?/div>
雖然采用合適的哈希方法能夠降低沖突的概率,但是沖突仍然是不可避免的,處理沖突的最常用方法就是“桶”算法:假設(shè)哈希表有m 個地址,就將其改為 m 個“桶”,其桶號與哈希地址一一對應(yīng),每個桶都用來存放互為同義詞的鍵,也就是如果兩個不同的鍵用哈希函數(shù)計算得到了同一個哈希地址,就將它們放到同一個桶中,檢索的時候在桶內(nèi)進行順序檢索。
2.2.4Java中的 Map 接口字典數(shù)據(jù)結(jié)構(gòu)如此重要,以至于實際開發(fā)中經(jīng)常需要使用它們。JDK 中提供了相關(guān)的類供我們使用,從而避免了自己開發(fā)字典類的麻煩。
在以前版本的JDK 中,最常使用的字典類就是 Dictionary 抽象類及其實現(xiàn)類 Hashtable ,不過在新版本的JDK 中不推薦讀者使用 Dictionary 抽象類而是使用Map 接口,并且由于 Dictionary 的實現(xiàn)類 Hashtable 也實現(xiàn)了Map 接口,所以我們沒有理由不使用 Map 接口。
Map接口有很多實現(xiàn)類,比如 HashMap 、 TreeMap 、 Hashtable 、 SortedMap 等,在第三方開源包中也有提供了更多功能的實現(xiàn)類,比如Apache-Commons 項目中的 LRUMap 。最常用的就是 HashMap 和 Hashtable ,它們最大的區(qū)別就是 Hashtable 是線程安全的,而 HashMap 則不是線程安全的,在使用的時候必須進行同步。由于JDK 中的工具類 java.util . Collections 提供了一個 synchronizedMap 方法,可以將非線程安全的Map 接口變量采用裝飾者模式改造成線程安全的,因此使用 HashMap 的場合更多一些,后邊的論述也將以 HashMap 為主。
2.3HashMapHashMap是 Map 接口的實現(xiàn)類中最常用的一個,熟練的掌握這個類的使用將會提高解決問題的速度 。
HashMap的主要方法
int size() :得到Map中“鍵-值對”的數(shù)量
boolean isEmpty() :Map是否是空的,也就是是否不含有任何“鍵-值對”
boolean containsKey(Object key) :Map中是否含有以key為鍵的“鍵-值對”
boolean containsValue(Object value) :Map中是否含有以 value 為值的“鍵-值對”
Object get(Object key) :從Map中得到以key為鍵的值,如果Map中不含有以key為鍵的“鍵-值對”則返回null
Object put(Object key, Object value) :向Map中存儲以key為鍵、value為值的“鍵-值對”
Object remove(Object key) :從Map中移除以key為鍵的“鍵-值對”
void putAll(Map t) :將另一個Map中的所有“鍵-值對”導(dǎo)入到此Map中
void clear() :清除所有“鍵-值對”
Set keySet() :得到所有的鍵
Collection values() :得到所有的值
Set entrySet() :得到所有的“鍵-值對”,Set中的類型是Map.Entry
歡迎光臨 (http://www.zg4o1577.cn/bbs/) |
Powered by Discuz! X3.1 |
主站蜘蛛池模板:
欧美成人免费在线视频
|
99精品久久久久久
|
美女在线观看av
|
在线免费小视频
|
在线国产一区
|
国产一级一级国产
|
欧美free性
|
欧美成人黄色小说
|
久久噜噜噜精品国产亚洲综合
|
欧美日韩综合视频
|
欧美精品在线看
|
国产精品美女久久久久久久久久久
|
黑人巨大精品欧美一区二区免费
|
亚洲午夜一区二区
|
成人影院免费视频
|
日韩国产精品一区二区三区
|
久操国产
|
欧美激情综合五月色丁香小说
|
蜜臀网站|
欧美精品91爱爱
|
a国产一区二区免费入口
|
国产精品国产精品国产专区不片
|
国产成人在线免费
|
成人av免费看
|
综合自拍
|
狠狠av|
毛片在线免费
|
一级毛片免费完整视频
|
国产高清美女一级a毛片久久w
|
天天色综
|
www.av7788.com|
自拍偷拍小视频
|
欧美日韩不卡合集视频
|
国产yw851.c免费观看网站
|
av男人天堂影院
|
久久久久久国产
|
成人午夜在线
|
欧美一级片中文字幕
|
日韩午夜
|
9999久久|
а√中文在线8
|