引
在各種數據結構(線性表、樹等)中,記錄在結構中的相對位置是隨機的。因此在機構中查找記錄的時須要進行一系列和keyword的比較。這一類的查找方法建立在“比較”的基礎上。查找的效率依賴於查找過程中所進行的比較次數。
之前我們介紹的各種基於比較的樹查找算法,這些查找算法的效率都將隨着數據記錄數的增長而下降。
不過有的比較慢(時間復雜度為O(n)),有的比較快(時間復雜度是O(logn))而已。這些查找算法的平均查找長度是在一種比較理想的情況下獲得的。
在實際應用其中,對數據結構中數據的頻繁添加和刪除將不斷地改變着數據的結構。
這些操作將可能導致某些數據結構退化為鏈表結構,那么其性能必定將下降。
為了避免出現這樣的情況而採取的調整措施。又不可避免的添加了程序的復雜程度以及操作的額外時間。
哈希表
理想的情況是 希望不經過不論什么比較,一次存取便能得到所查的記錄。那就必須在記的存儲位置和它的keyword之間建立一個確定的相應關系f,使每一個keyword和一個唯一的存儲位置相相應。因而在查找時。僅僅要依據這個相應關系f找到給定值K的像f(K)。由此,不須要進行比較便可直接取得所查記錄。在此,我們稱這個相應關系為哈希(Hash)函數。按這個思想建立的表為 哈希表。在哈希表中對於不同的keyword可能得到同一哈希地址,這樣的現象稱做沖突。在普通情況下。沖突僅僅能盡可能地降低,而不能全然避免。由於哈希函數是從keyword集合到地址集合的映像。通常keyword的集合比較大,它的元素包含全部可能的keyword。而地址集合的元素僅為哈希表中的地址值。在普通情況下, 哈希函數是一個壓縮映像函數。這就不可避免的要產生沖突。
哈希樹(HashTree)算法就是要提供一種在理論上和實際應用中均能有效地處理沖突的方法。一般的哈希(Hash)算法都是O(1)的,並且基本是以空間換時間。這非常easy導致對存儲空間無限制的需求。
本文中哈希樹(HashTree)算法在實際操作中使用了一些技巧使得對空間的需求控制在一定范圍內。即空間需求僅和所須要存儲的對象個數有關,不會無限制地“膨脹”下去。
哈希樹的理論基礎
簡單地說就是:n個不同的質數能夠“分辨”的連續整數的個數和他們的乘積相等。
“分辨”就是指這些連續的整數不可能有全然同樣的余數序列。
(這個定理的證明詳見:http://wenku.baidu.com/view/16b2c7abd1f34693daef3e58.html)
比如:
從2起的連續質數。連續10個質數就能夠分辨大約M(10) =2*3*5*7*11*13*17*19*23*29= 6464693230 個數,已經超過計算機中經常使用整數(32bit)的表達范圍。連續100個質數就能夠分辨大約M(100) = 4.711930 乘以10的219次方。
而依照眼下的CPU水平,100次取余的整數除法操作差點兒不算什么難事。在實際應用中。總體的操作速度往往取決於節點將keyword裝載內存的次數和時間。一般來說。裝載的時間是由keyword的大小和硬件來決定的;在同樣類型keyword和同樣硬件條件下,實際的總體操作時間就主要取決於裝載的次數。
他們之間是一個成正比的關系。
插入
我們選擇質數分辨算法來建立一棵哈希樹。
選擇從2開始的連續質數來建立一個十層的哈希樹。第一層結點為根結點。根結點下有2個結點。第二層的每一個結點下有3個結點。依此類推,即每層結點的子節點數目為連續的質數。
到第十層,每一個結點下有29個結點。
同一結點中的子結點。從左到右代表不同的余數結果。
比如:第二層結點下有三個子節點。那么從左到右分別代表:除3余0,除3余1。除3余2.
對質數進行取余操作得到的余數決定了處理的路徑。
結點結構:結點的keyword(在整個樹中是唯一的),結點的數據對象。結點是否被占領的標志位(標志位為真時,keyword才被覺得是有效的),和結點的子結點數組。
哈希樹的節點結構
struct Node { keyType key ; ValueType value ; bool occupied ; //用occupied來表示節點是否被占領。假設節點的keyword(key)有效。那么occupied應該設置位true,否則設置為false。(假設在建立當初就建立全部的節點。那么所消耗的計算時間和磁盤空間是巨大的。struct Node* subNodes[1] ; //我們用subNodes[i]來表示節點的第i個子節點的地址。(此技術在跳躍表中有介紹,可翻看前面博客) } ;
在實際使用其中,僅僅須要初始化根節點就能夠開始工作。
子節點的建立是在有很多其它的數據進入到哈希樹中的時候建立的。因此能夠說哈希樹和其它樹一樣是一個動態結構。)
以下我們以隨機的10個數的插入為例,來圖解HashTree的插入過程,這個史上最清晰的圖解,你一定能看的明確^_^
有讀者可能有疑問,假設一直沖突下去怎么辦?首先,若keyword是整型。我們的10層哈希樹全然能夠分辨出來它們,這是質數分辨算法決定的。
(我們事實上也能夠把全部的鍵-值節點放在哈希樹的第10層葉節點處,這第10層的滿節點數就包括了全部的整數個數。可是假設這樣處理的話,全部的非葉子節點作為鍵-值節點的索引,這樣使樹結構龐大,浪費空間)
【這里沒有說的太清楚,此圖是以2開始的連續質數創建的,即:從上到下的層級中的每一個節點中的子樹個數為2、3、5、7、11、13、17、19、23、29。第一層中的每一個節點的子樹個數為2,第二層中的每一個節點子樹個數為5.。。。。
上圖中的子樹上的數字。是其父節點的子樹指針數組的索引值】
查找
哈希樹的節點查找過程和節點插入過程類似,就是對keyword用質數序列取余,依據余數確定下一節點的分叉路徑,直到找到目標節點。
如上圖,最小”哈希樹(HashTree)在從4G個對象中找出所匹配的對象,比較次數不超過10次。也就是說:最多屬於O(10)。在實際應用中,調整了質數的范圍,使得比較次數一般不超過5次。也就是說:最多屬於O(5)。
因此能夠依據自身須要在時間和空間上尋求一個平衡點。
刪除
哈希樹的節點刪除過程也非常easy。哈希樹在刪除的時候,並不做不論什么結構調整。
僅僅是先查到到要刪除的節點,然后把此節點的“占位標記”置為false就可以(即表示此節點為空節點。但並不進行物理刪除)。
長處
1、結構簡單
從哈希樹的結構來說。很的簡單。每層節點的子節點個數為連續的質數。子節點能夠隨時創建。因此哈希樹的結構是動態的,也不像某些哈希算法那樣須要長時間的初始化過程。哈希樹也沒有必要為不存在的keyword提前分配空間。
須要注意的是哈希樹是一個單向添加的結構,即隨着所須要存儲的數據量添加而增大。
即使數據量降低到原來的數量,可是哈希樹的總節點數不會降低。
這樣做的目的是為了避免結構的調整帶來的額外消耗。
2、查找迅速
從算法過程我們能夠看出,對於整數,哈希樹層級最多能添加到10。
因此最多僅僅須要十次取余和比較操作,就能夠知道這個對象是否存在。
這個在算法邏輯上決定了哈希樹的優越性。
一般的樹狀結構。往往隨着層次和層次中節點數的添加而導致很多其它的比較操作。操作次數能夠說無法准確確定上限。而哈希樹的查找次數和元素個數沒有關系。假設元素的連續keyword總個數在計算機的整數(32bit)所能表達的最大范圍內,那么比較次數就最多不會超過10次。通常低於這個數值。
3、結構不變
從刪除算法中能夠看出,哈希樹在刪除的時候,並不做不論什么結構調整。這個也是它的一個很好的長處。常規樹結構在添加元素和刪除元素的時候都要做一定的結構調整,否則他們將可能退化為鏈表結構,而導致查找效率的減少。哈希樹採取的是一種“見縫插針”的算法,從來不用操心退化的問題,也不必為優化結構而採取額外的操作。因此大大節約了操作時間。
缺點
1、非排序性
哈希樹不支持排序。沒有順序特性。
假設在此基礎上不做不論什么改進的話並試圖通過遍歷來實現排序,那么操作效率將遠遠低於其它類型的數據結構。
關於超長字符串的問題
我們能夠用MD5等消息壓縮算法來生成定長的整數。
【關於MD5】
維基鏈接:http://zh.wikipedia.org/wiki/MD5MD5(Message Digest Algorithm 消息摘要算法第五版)
一種被廣泛使用的password散列函數。能夠產生出一個128位(16字節)的散列值(hash value),用於確保信息傳輸完整一致。
MD5算法具有下面特點:
1、壓縮性:隨意長度的數據。算出的MD5值長度都是固定的。
2、easy計算:從原數據計算出MD5值非常easy。
3、抗改動性:對原數據進行不論什么改動,哪怕僅僅改動1個字節。所得到的MD5值都有非常大差別。
4、弱抗碰撞:已知原數據和其MD5值,想找到一個具有同樣MD5值的數據(即偽造數據)是很困難的。
5、強抗碰撞:想找到兩個不同的數據,使它們具有同樣的MD5值,是很困難的。
(1996年后被證實存在弱點。能夠被加以破解,對於須要高度安全性的數據。專家一般建議改用其它算法,如SHA-1)
對於超長字符串,我們能夠用MD5算法生成一個128bit的整數。然后用RadixTree(翻看前面博客)來存儲這個大整數。或者使用哈希樹來存儲,對於這種大整數。我們不能簡單地使用計算機的整數來做除法,而是使用程序模擬人工的除法方式來做除法並獲得余數。
這樣,使用MD5和選用更大的質數相結合的辦法。這樣就能夠使得通過層次比較少的哈希樹來獲得對keyword區間的完整覆蓋。這樣就降低了比較操作的次數,並提高總體的工作效率。
應用
哈希樹能夠廣泛應用於那些須要對大容量數據進行高速匹配操作的地方。
比如:數據庫索引系統、短信息中的收條匹配、大量號碼路由匹配、信息過濾匹配。
哈希樹不須要額外的平衡和防止退化的操作。效率十分理想。
【參考】
http://baike.baidu.com/view/10403049.htm
http://wenku.baidu.com/view/16b2c7abd1f34693daef3e58.html