基礎(chǔ)篇(六)——查找

一、相關(guān)定義

查找——查找就是根據(jù)給定的某個(gè)值,在查找表中確定一個(gè)其關(guān)鍵字等于給定值的數(shù)據(jù)元素(或記錄)。所有這些需要被查的數(shù)據(jù)所在的集合,它的統(tǒng)稱叫查找表。

查找表——是由同一類型的數(shù)據(jù)元素(或記錄)構(gòu)成的集合。

關(guān)鍵字——關(guān)鍵字是數(shù)據(jù)元素中某個(gè)數(shù)據(jù)項(xiàng)的值,又稱為鍵值,用它可以標(biāo)識(shí)一個(gè)數(shù)據(jù)元素。也可以標(biāo)識(shí)一個(gè)記錄的某個(gè)數(shù)據(jù)項(xiàng)(字段),稱為關(guān)鍵碼。若此關(guān)鍵字可以唯一標(biāo)識(shí)一個(gè)記錄,則稱此關(guān)鍵字為主關(guān)鍵字。主關(guān)鍵字所在的數(shù)據(jù)項(xiàng)稱為主關(guān)鍵碼。對(duì)于那些可以識(shí)別多個(gè)數(shù)據(jù)元素(或記錄)的關(guān)鍵字,我們稱為次關(guān)鍵字。



查找表按照操作方式來分為兩大種:靜態(tài)查找表和動(dòng)態(tài)查找表。
靜態(tài)查找表——只作查找操作的查找表。它的主要操作有:
(1)查詢某個(gè)“特定的”數(shù)據(jù)元素是否在查找表中。
(2)檢索某個(gè)“特定的”數(shù)據(jù)元素和各種屬性。
動(dòng)態(tài)查找表——在查找過程中同時(shí)插入查找表中不存在的數(shù)據(jù)元素,或者從查找表中刪除已經(jīng)存在的某個(gè)數(shù)據(jù)元素。動(dòng)態(tài)查找表的操作有兩個(gè):
(1)查找時(shí)插入數(shù)據(jù)元素。
(2)查找時(shí)刪除數(shù)據(jù)元素。

為了提高查找的效率,需要專門為查找操作設(shè)置數(shù)據(jù)結(jié)構(gòu),這種面向查找操作的數(shù)據(jù)結(jié)構(gòu)稱為查找結(jié)構(gòu)。從邏輯上來說,查找所基于的數(shù)據(jù)結(jié)構(gòu)是集合,集合中的記錄之間沒有本質(zhì)關(guān)系。可是要想獲得較高的查找性能,就不能不改變數(shù)據(jù)元素之間的關(guān)系,在存儲(chǔ)時(shí)可以將查找集合組織成表、樹等結(jié)構(gòu)。

二、順序表查找(時(shí)間復(fù)雜度為O(n))

順序查找,又叫線性查找,是最基本的查找技術(shù),它的查找過程是:從表中第一個(gè)(或最后一個(gè))記錄開始,逐個(gè)進(jìn)行記錄的關(guān)鍵字和給定值比較,若某個(gè)記錄的關(guān)鍵字和給定值相等,則查找成功;如果直到最后一個(gè)(或第一個(gè))記錄,其關(guān)鍵字和給定值比較都不等時(shí),則表中沒有所查的記錄,查找不成功。

優(yōu)缺點(diǎn):

順序查找是有很大缺點(diǎn)的,n很大時(shí),查找效率極為低下,不過優(yōu)點(diǎn)也是有的,這個(gè)算法非常簡(jiǎn)單,對(duì)靜態(tài)查找表的記錄沒有任何要求,在一些小型數(shù)據(jù)的查找時(shí),是可以適用的。

三、有序表查找(線性有序時(shí)的查找)

3.1折半查找

折半查找技術(shù),又叫做二分查找。它的前提是線性表中的記錄必須是關(guān)鍵碼有序(通常從小到大有序),線性表必須采用順序存儲(chǔ)。折半查找的基本思想是:在有序表中,取中間記錄作為比較對(duì)象,若給定值與中間記錄的關(guān)鍵字相等,則查找成功;若給定值小于中間記錄的關(guān)鍵字,則在中間記錄的左半?yún)^(qū)繼續(xù)查找;若給定值大于中間記錄的關(guān)鍵字,則在中間記錄的右半?yún)^(qū)繼續(xù)查找。不斷重復(fù)上述過程,直到查找成功,或所有查找區(qū)域無記錄,查找失敗為止。
例如:100以內(nèi)的正整數(shù)猜數(shù)


優(yōu)缺點(diǎn):

由于折半查找的前提條件是需要有序表順序存儲(chǔ),對(duì)于靜態(tài)查找表,一次排序后不再變化,這樣的算法已經(jīng)比較好了。但對(duì)于需要頻繁執(zhí)行插入和刪除操作的數(shù)據(jù)集來說,維護(hù)有序的排序會(huì)帶來不小的工作量,那就不建議使用。

3.2插值查找

插值查找是根據(jù)要查找的關(guān)鍵字key與查找表中最大最小記錄的關(guān)鍵字比較后的查找方法,其核心就在于插值的計(jì)算公式{key-a[low]}/{a[high]-a[low]}。

優(yōu)缺點(diǎn):

它和折半查找的時(shí)間復(fù)雜度一樣,但對(duì)于表長(zhǎng)較大,而關(guān)鍵字分布又比較均勻的查找表來說,插值查找算法的平均性能比折半查找要好很多。

3.3斐波那契查找(是一種有序查找)

斐波那契查找是一種有序查找,它是利用了黃金分割原理來實(shí)現(xiàn)的。


優(yōu)缺點(diǎn):

斐波那契查找的時(shí)間復(fù)雜度和折半查找、插值查找一樣,但就平均性能來說,斐波那契查找要優(yōu)于折半查找。

四、線性索引查找

索引就是把一個(gè)關(guān)鍵字與它對(duì)應(yīng)的記錄相關(guān)聯(lián)的過程,一個(gè)索引由若干個(gè)索引項(xiàng)構(gòu)成,每個(gè)索引項(xiàng)至少應(yīng)包含關(guān)鍵字和其對(duì)應(yīng)的記錄在存儲(chǔ)器中的位置等信息。索引技術(shù)是組織大型數(shù)據(jù)庫(kù)以及磁盤文件的一項(xiàng)重要技術(shù)。

索引按照結(jié)構(gòu)可以分為線性索引、樹形索引和多級(jí)索引。此處只介紹線性索引。所謂線性索引就是將索引項(xiàng)集合組織為線性結(jié)構(gòu),也稱為索引表。重點(diǎn)介紹三種線性索引:稠密索引、分塊索引和倒排索引。

4.1稠密索引

稠密索引是指在線性索引中,將數(shù)據(jù)集中的每一個(gè)記錄對(duì)應(yīng)一個(gè)索引項(xiàng),如圖所示:



對(duì)于稠密索引這個(gè)索引表來說,索引項(xiàng)是一定按照關(guān)鍵碼有序的排列。索引項(xiàng)有序也就意味著,我們要查找關(guān)鍵字時(shí),可以用折半、插值、斐波那契等有序查找算法,大大提高了效率。

優(yōu)缺點(diǎn):

如果數(shù)據(jù)集非常大,比如上億,那也就意味著索引也得同樣的數(shù)據(jù)集長(zhǎng)度規(guī)模,對(duì)于內(nèi)存有限的計(jì)算機(jī)來說,可能就需要反復(fù)去訪問磁盤,查找性能反而大大下降了。

4.2分塊索引

稠密索引由于索引項(xiàng)與數(shù)據(jù)集的記錄個(gè)數(shù)相同,所以空間代價(jià)很大。為了減少索引項(xiàng)的個(gè)數(shù),可以對(duì)數(shù)據(jù)集進(jìn)行分塊,使其分塊有序,然后再對(duì)每一塊建立一個(gè)索引項(xiàng),從而減少索引項(xiàng)的個(gè)數(shù)。

分塊有序,是把數(shù)據(jù)集的記錄分成了若干塊,并且這些塊滿足兩個(gè)條件:
(1)塊內(nèi)無序,即每一塊內(nèi)的記錄不要求有序。當(dāng)然,如果能讓塊內(nèi)有序,對(duì)查找來說更加理想,不過這就需要付出大量時(shí)間和空間的代價(jià),因此通常不要求塊內(nèi)有序。
(2)塊間有序,例如,要求第二塊所有記錄的關(guān)鍵字均要大于第一塊中所有記錄的關(guān)鍵字,第三塊的所有記錄的關(guān)鍵字均要大于第二塊的所有記錄的關(guān)鍵字.......因?yàn)橹挥袎K間有序,才有可能給查找?guī)硇省?/p>

對(duì)于分塊有序的數(shù)據(jù)集,將每塊對(duì)應(yīng)一個(gè)索引項(xiàng),這種索引方法叫做分塊索引。如圖所示:此分塊索引的索引項(xiàng)結(jié)構(gòu)分為三個(gè)數(shù)據(jù)項(xiàng)。
(1)最大關(guān)鍵碼——它存儲(chǔ)每一塊中的最大關(guān)鍵字,這樣的好處在于可以使得在它之后的下一塊中的最小關(guān)鍵字也能比這一塊最大的關(guān)鍵字要大。
(2)存儲(chǔ)了塊中記錄的個(gè)數(shù),以便于循環(huán)時(shí)使用。
(3)用于指向塊首數(shù)據(jù)元素的指針,便于開始對(duì)這一塊中記錄進(jìn)行遍歷。



在分塊索引表中查找,就是分兩步進(jìn)行:
1.在分塊索引表中查找要查關(guān)鍵字所在的塊。由于分塊索引表是塊間有序的,因此很容易利用折半、插值等算法得到結(jié)果。
2.根據(jù)塊首指針找到相應(yīng)的塊,并在塊中順序查找關(guān)鍵碼。因?yàn)閴K中可以是無序的,因此只能順序查找。

優(yōu)缺點(diǎn):

分塊索引的效率比之順序查找的O(n)是高了不少,不過顯然它與折半查找相比還有不小的差距。因此在確定所在塊的過程中,由于塊間有序,所以可以應(yīng)用折半、插值等手段來提高效率。總的來說,分塊索引在兼顧了對(duì)細(xì)分塊不需要有序的情況下,大大增加了整體查找的速度,所以普遍被用于數(shù)據(jù)庫(kù)表查找等技術(shù)的應(yīng)用中。

4.3倒排索引

例如:
1.Books and friends should be few but good.
2.A good book is a good friend.



在這里,這個(gè)單詞表就是索引表,索引項(xiàng)的通用結(jié)構(gòu)是:
1.次關(guān)鍵碼,例如上面的“英文單詞”。
2.記錄號(hào)表,例如上面的“文章編號(hào)”。
其中記錄號(hào)表存儲(chǔ)具有相同次關(guān)鍵字的所有記錄的記錄號(hào)(可以是指向記錄的指針或者是該記錄的主關(guān)鍵字)。這樣的索引方法就是倒排索引。

優(yōu)缺點(diǎn):

倒排索引的優(yōu)點(diǎn)顯然就是查找記錄非常快,基本等于生成索引表后,查找時(shí)都不用去讀取記錄,就可以得到結(jié)果。但它的缺點(diǎn)是這個(gè)記錄號(hào)不定長(zhǎng),維護(hù)比較困難。

五、二叉排序樹(動(dòng)態(tài)查找表)

對(duì)集合{62,88,58,47,35,73,51,99,37,93}做查找,考慮用二叉樹結(jié)構(gòu),而且是排好序的二叉樹來創(chuàng)建,如圖所示:



二叉排序樹又稱為二叉查找樹。它或者是一顆空樹,或者是具有下列性質(zhì)的二叉樹:
(1)若它的左子樹不為空,則左子樹上所有結(jié)點(diǎn)的值均小于它的根結(jié)點(diǎn)的值。
(2)若它的右子樹不為空,則右子樹上所有結(jié)點(diǎn)的值均大于它的根結(jié)點(diǎn)的值。
(3)它的左、右子樹也分別為二叉排序樹。

優(yōu)缺點(diǎn):

構(gòu)造一棵二叉排序樹的目的,其實(shí)并不是為了排序,而是為了提高查找和插入刪除關(guān)鍵字的速度。不管如何,在一個(gè)有序數(shù)據(jù)集上的查找,速度總要快于無序的數(shù)據(jù)集的,而二叉排序樹這種非線性的結(jié)構(gòu),也有利于插入和刪除的實(shí)現(xiàn)。

二叉排序樹總結(jié):

二叉排序樹是以鏈接的方式存儲(chǔ),保持了鏈接存儲(chǔ)結(jié)構(gòu)在執(zhí)行插入或刪除操作時(shí)不用移動(dòng)元素的優(yōu)點(diǎn),只要找到合適的插入和刪除位置后,僅需修改鏈接指針即可。插入刪除的時(shí)間性能比較好。而對(duì)于二叉排序樹的查找,走的就是從根結(jié)點(diǎn)到要查找的結(jié)點(diǎn)的路徑,其比較次數(shù)等于給定值的結(jié)點(diǎn)在二叉排序樹的層數(shù)。極端情況,最少為1次,即根結(jié)點(diǎn)就是要找的結(jié)點(diǎn),最多也不會(huì)超過數(shù)的深度。也就是說,二叉排序樹的查找性能取決于二叉排序樹的形狀。

六、平衡二叉樹(AVL樹)

平衡二叉樹是一種二叉排序樹,其中左子樹和右子樹的高度差至多等于1。將二叉樹上結(jié)點(diǎn)的左子樹深度減去右子樹深度的值稱為平衡因子BF,那么平衡二叉樹上所有結(jié)點(diǎn)的平衡因子只可能是-1,0和1。只要二叉樹上有一個(gè)結(jié)點(diǎn)的平衡因子的絕對(duì)值大于1,則該二叉樹就是不平衡的。

距離插入結(jié)點(diǎn)最近的,且平衡因子的絕對(duì)值大于1的結(jié)點(diǎn)為根的子樹,稱為最小不平衡子樹。如圖所示:

平衡二叉樹的實(shí)現(xiàn)原理:

平衡二叉樹構(gòu)建的基本思想就是在構(gòu)建二叉排序樹的過程中,每當(dāng)插入一個(gè)結(jié)點(diǎn)時(shí),先檢查是否因插入而破壞了樹的平衡性,若是,則找出最小不平衡子樹。在保持二叉排序樹特性的前提下,調(diào)整最小不平衡子樹中各結(jié)點(diǎn)之間的鏈接關(guān)系,進(jìn)行相應(yīng)的旋轉(zhuǎn),使之成為新的平衡子樹。(BF為正右旋,BF為負(fù)左旋)


平衡二叉樹總結(jié):

如果需要查找的集合本身沒有順序,在頻繁查找的同時(shí)也需要經(jīng)常的插入和刪除操作,顯然我們需要構(gòu)建一棵二叉排序樹,但是不平衡的二叉排序樹,查找效率是非常低的,因此需要在構(gòu)建時(shí),就讓這棵二叉排序樹是平衡二叉樹,此時(shí)時(shí)間復(fù)雜度和有序表查找一樣。

七、多路查找樹(B樹)

多路查找樹,其每一個(gè)結(jié)點(diǎn)的孩子數(shù)可以多于兩個(gè),且每一個(gè)結(jié)點(diǎn)處可以存儲(chǔ)多個(gè)元素。由于它是查找樹,所有元素之間存在某種特定的排序關(guān)系。

7.1 2-3樹

2-3樹是這樣一棵多路查找樹:其中的每一個(gè)結(jié)點(diǎn)都具有兩個(gè)孩子(稱之為2結(jié)點(diǎn))或三個(gè)孩子(稱之為3結(jié)點(diǎn))。

一個(gè)2結(jié)點(diǎn)包含一個(gè)元素和兩個(gè)孩子(或沒有孩子),且與二叉排序樹類似,左子樹包含的元素小于該元素,右子樹包含的元素大于該元素。不過,與二叉排序樹不一樣的是,這個(gè)2結(jié)點(diǎn)要么沒有孩子,要么就有兩個(gè)孩子,不能只有一個(gè)孩子。

一個(gè)3結(jié)點(diǎn)包含一小一大兩個(gè)元素和三個(gè)孩子(或沒有孩子),一個(gè)3結(jié)點(diǎn)要么沒有孩子,要么具有3個(gè)孩子。如果某個(gè)3結(jié)點(diǎn)有孩子的話,左子樹包含小于較小元素的元素,右子樹包含大于較大元素的元素,中間子樹包含介于兩元素之間的元素。

并且2-3樹中所有的葉子都在同一層次上。如圖所示:是一個(gè)有效的2-3樹。

2-3樹小結(jié):

2-3樹復(fù)雜的地方就是新結(jié)點(diǎn)的插入和已有結(jié)點(diǎn)的刪除。畢竟,每個(gè)結(jié)點(diǎn)可能是2結(jié)點(diǎn)也可能是3結(jié)點(diǎn),要保證所有葉子都在同一層次,是需要進(jìn)行復(fù)雜操作的。

7.2 2-3-4樹

2-3-4樹是在2-3樹的基礎(chǔ)上增加了4結(jié)點(diǎn)的使用。一個(gè)4結(jié)點(diǎn)包含大中小三個(gè)元素和四個(gè)孩子(或沒有孩子),一個(gè)4結(jié)點(diǎn)要么沒有孩子,要么具有4個(gè)孩子。如果某個(gè)結(jié)點(diǎn)有孩子的話,左子樹包含小于最小元素的元素;第二子樹包含大于最小元素,小于第二元素的元素;第三子樹包含大于第二元素,小于最大元素的元素;右子樹包含大于最大元素的元素。構(gòu)建數(shù)組為{7,1,2,5,6,9,8,4,3}的2-3-4樹的過程,如圖所示:

7.3 B樹

B樹是一種平衡的多路查找樹,2-3樹和2-3-4樹都是B樹的特例。結(jié)點(diǎn)最大的孩子數(shù)目稱為B樹的階,因此,2-3樹是3階B樹,2-3-4樹是4階B樹。
一個(gè)m階的B樹具有如下屬性:
(1)如果根結(jié)點(diǎn)不是葉節(jié)點(diǎn),則其至少有兩棵子樹。
(2)每一個(gè)非根的分支結(jié)點(diǎn)都有k-1個(gè)元素和k個(gè)孩子,其中m/2<=k<=m。每一個(gè)葉子結(jié)點(diǎn)n都有k-1個(gè)元素,其中m/2<=k<=m。
(3)所有葉子結(jié)點(diǎn)都位于同一層次。
(4)每個(gè)結(jié)點(diǎn)中的元素從小到大排列,結(jié)點(diǎn)當(dāng)中k-1個(gè)元素正好是k個(gè)孩子包含的元素的值域分劃。
(5)所有分支結(jié)點(diǎn)包含下列信息數(shù)據(jù)(n,A0,K1,A1,K2,A2,...Kn,An),其中:Ki(i=1,2,...n)為關(guān)鍵字,且Ki<Ki+1(i=1,2,...n-1);Ai(i=0,2,...n)為指向子樹根結(jié)點(diǎn)的指針,且指針Ai-1所指子樹中所有結(jié)點(diǎn)的關(guān)鍵字均小于Ki(i=1,2,...n),An所指子樹中所有結(jié)點(diǎn)的關(guān)鍵字均大于Kn,n([m/2]-1<=n<=m-1)為關(guān)鍵字的個(gè)數(shù)(或n+1為子樹的個(gè)數(shù))。

將下圖中的2-3-4樹轉(zhuǎn)成B樹示意圖如下:左側(cè)灰色方塊表示當(dāng)前結(jié)點(diǎn)的元素個(gè)數(shù)。

B樹小結(jié):

在B樹上查找的過程是一個(gè)順時(shí)針查找結(jié)點(diǎn)和在結(jié)點(diǎn)中查找關(guān)鍵字的交叉過程。由于B樹每結(jié)點(diǎn)可以具有比二叉樹多得多的元素,所以與二叉樹的操作不同,它們減少了必須訪問結(jié)點(diǎn)和數(shù)據(jù)塊的數(shù)量,從而提高了性能。可以說,B樹的數(shù)據(jù)結(jié)構(gòu)就是為內(nèi)外存的數(shù)據(jù)交互準(zhǔn)備的。

7.4 B+樹

B+樹是應(yīng)文件系統(tǒng)所需而出的一種B樹的變形樹。在B樹中,每一個(gè)元素在該樹中只出現(xiàn)一次,有可能在葉子結(jié)點(diǎn)上,也有可能在分支結(jié)點(diǎn)上。而在B+樹中,出現(xiàn)在分支結(jié)點(diǎn)中的元素會(huì)被當(dāng)做它們?cè)谠摲种ЫY(jié)點(diǎn)位置的中序后繼者(葉子結(jié)點(diǎn))中再次列出。另外,每一個(gè)葉子結(jié)點(diǎn)都會(huì)保存一個(gè)指向后一葉子結(jié)點(diǎn)的指針。如圖所示就是一棵B+樹,灰色關(guān)鍵字即是根結(jié)點(diǎn)中的關(guān)鍵字在葉子結(jié)點(diǎn)再次列出,并且所有葉子結(jié)點(diǎn)都鏈接在一起。


一棵m階的B+樹和m階的B樹的差異在于:
(1)有n棵子樹的結(jié)點(diǎn)中包含有n個(gè)關(guān)鍵字。
(2)所有的葉子結(jié)點(diǎn)包含全部關(guān)鍵字的信息,及指向含這些關(guān)鍵字記錄的指針,葉子結(jié)點(diǎn)本身依關(guān)鍵字的大小自小到大順序鏈接。
(3)所有分支結(jié)點(diǎn)可以看成是索引,結(jié)點(diǎn)中僅含有其子樹中的最大(或最小)關(guān)鍵字。

B+樹小結(jié):

B+樹的結(jié)構(gòu)特別適合帶有范圍的查找。B+樹的插入、刪除過程也都與B樹類似,只不過插入和刪除的元素都是在葉子結(jié)點(diǎn)上進(jìn)行而已。

八、散列表查找(哈希表)

散列技術(shù)是在記錄的存儲(chǔ)位置和它的關(guān)鍵字之間建立一個(gè)確定的對(duì)應(yīng)關(guān)系f,使得每個(gè)關(guān)鍵字key對(duì)應(yīng)一個(gè)存儲(chǔ)位置f(key)。對(duì)應(yīng)關(guān)系f稱為散列函數(shù),又稱為哈希函數(shù)。按這個(gè)思想,采用散列技術(shù)將記錄存儲(chǔ)在一塊聯(lián)系的存儲(chǔ)空間中,這塊連續(xù)存儲(chǔ)空間稱為散列表或哈希表。那么關(guān)鍵字對(duì)應(yīng)的記錄存儲(chǔ)位置稱為散列地址。

散列表查找步驟:

(1)在存儲(chǔ)時(shí),通過散列函數(shù)計(jì)算記錄的散列地址,并按此地址存儲(chǔ)該記錄。
(2)當(dāng)查找記錄時(shí),我們通過同樣的散列函數(shù)計(jì)算記錄的散列地址,按此散列地址訪問該記錄。

散列表查找小結(jié):

散列技術(shù)既是一種存儲(chǔ)方法也是一種查找方法。散列技術(shù)的記錄之間不存在什么邏輯關(guān)系,它只與關(guān)鍵字有關(guān)。因此,散列主要是面向查找的存儲(chǔ)結(jié)構(gòu)。

散列技術(shù)最適合的求解問題是查找與給定值相等的記錄。對(duì)于查找來說,簡(jiǎn)化了比較過程,效率就大大提高。但散列技術(shù)也有缺點(diǎn):
(1)比如那種同樣的關(guān)鍵字,它能對(duì)應(yīng)很多記錄的情況,卻不適合用散列技術(shù)。
(2)同樣散列表也不適合范圍查找。

九、散列函數(shù)的構(gòu)造方法

兩個(gè)關(guān)鍵字key1不等于key2,但是卻有f(key1)=f(key2),這種現(xiàn)象叫做沖突,并把key1和key2稱為這個(gè)散列函數(shù)的同義詞。

好的散列函數(shù)有兩個(gè)原則:
(1)計(jì)算簡(jiǎn)單:散列函數(shù)的計(jì)算時(shí)間不應(yīng)該超過其他查找技術(shù)與關(guān)鍵字比較的時(shí)間。
(2)散列地址分布均勻:盡量讓散列地址均勻的分布在存儲(chǔ)空間中,這樣可以保證存儲(chǔ)空間的有效利用,并減少為處理沖突而耗費(fèi)的時(shí)間。

9.1直接定址法

如果要統(tǒng)計(jì)80后出生年份的人口數(shù),如表所示,我們對(duì)出生年份這個(gè)關(guān)鍵字可以用年份減去1980來作為地址,此時(shí)f(key)=key-1980。


取關(guān)鍵字的某個(gè)線性函數(shù)值為散列地址,即:f(key)=a*key+b(a、b為常數(shù))

小結(jié):

這樣的散列函數(shù)優(yōu)點(diǎn)就是簡(jiǎn)單、均勻,也不會(huì)產(chǎn)生沖突,但問題是這需要事先知道關(guān)鍵字的分布情況,適合查找表較小且連續(xù)的情況。由于這樣的限制,在現(xiàn)實(shí)應(yīng)用中,此方法雖然簡(jiǎn)單,但卻不常用。

9.2數(shù)字分析法

如果關(guān)鍵字是位數(shù)較多的數(shù)字,例如電話號(hào),如表所示:



選擇后面的四位稱為散列地址就是不錯(cuò)的選擇。如果這樣的抽取工作還是容易產(chǎn)生沖突,還可以對(duì)抽取出來的數(shù)字再進(jìn)行反轉(zhuǎn)、右環(huán)移位、左環(huán)移位等方法。總的目的就是為了提供一個(gè)散列函數(shù),能夠合理的將關(guān)鍵字分配到散列表的各位置。

小結(jié):

抽取方法是使用關(guān)鍵字的一部分來計(jì)算散列存儲(chǔ)位置的方法,這在散列函數(shù)中是常常用到的手段。數(shù)字分析法通常適合處理關(guān)鍵字位數(shù)比較大的情況,如果事先知道關(guān)鍵字的分布且關(guān)鍵字的若干位分布較均勻,就可以考慮用這個(gè)方法。

9.3平均取中法

如果關(guān)鍵字是1234,那么它的平方就是1522756,再抽取中間的三位227用做散列地址。

小結(jié):

平均取中法比較適合于不知道關(guān)鍵字的分布、而位數(shù)又不是很大的情況。

9.4折疊法

折疊法是將關(guān)鍵字從左到右分割成位數(shù)相等的幾部分(注意最后一部分位數(shù)不夠時(shí)可以短些),然后將這幾部分疊加求和,并按散列表表長(zhǎng),取后幾位作為散列地址。

小結(jié):

折疊法事先不需要知道關(guān)鍵字的分布,適合關(guān)鍵字位數(shù)較多的情況。

9.5除留余數(shù)法

此方法為最常用的構(gòu)造散列函數(shù)方法。對(duì)于列表長(zhǎng)為m的散列函數(shù)公式為:f(key)=key mod p (p<=m)
mod是取模。事實(shí)上,這方法不僅可以對(duì)關(guān)鍵字直接取模,也可在折疊、平方取中后再取模。很顯然,本方法的關(guān)鍵就在于選擇合適的p,p如果選得不好就會(huì)容易產(chǎn)生同義詞。

9.6隨機(jī)數(shù)法

選擇一個(gè)隨機(jī)數(shù),取關(guān)鍵字的隨機(jī)函數(shù)值為它的散列地址。也就是f(key)=random(key)。此處的random是隨機(jī)函數(shù)。當(dāng)關(guān)鍵字的長(zhǎng)度不等時(shí),采用這個(gè)方法構(gòu)造散列函數(shù)是比較合適的。

十、處理散列沖突的方法

開放定址法、再散列函數(shù)法、鏈地址法、公共溢出區(qū)法

總結(jié)

二叉排序樹是動(dòng)態(tài)查找最重要的數(shù)據(jù)結(jié)構(gòu),它可以在兼顧查找性能的基礎(chǔ)上,讓插入和刪除也變得效率較高。不過為了達(dá)到最優(yōu)的狀態(tài),二叉排序樹最好是構(gòu)造成平衡的二叉樹才最佳。

B樹這種數(shù)據(jù)結(jié)構(gòu)是針對(duì)內(nèi)存與外存之間的存取而專門設(shè)計(jì)的。由于內(nèi)外存的查找性能更多取決于讀取的次數(shù),因此在設(shè)計(jì)中要考慮B樹的平衡和層次。

散列表是一種非常高效的查找數(shù)據(jù)結(jié)構(gòu),在原理上也與前面的查找不盡相同,它回避了關(guān)鍵字之間反復(fù)比較的繁瑣,而是直接一步到位查找結(jié)果。當(dāng)然,這也就帶來了記錄之間沒有任何關(guān)聯(lián)的弊端。應(yīng)該說,散列表對(duì)于那種性能要求高,記錄之間關(guān)系無要求的數(shù)據(jù)有非常好的適用性

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,316評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,481評(píng)論 3 415
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,241評(píng)論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,939評(píng)論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,697評(píng)論 6 409
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,182評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,247評(píng)論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,406評(píng)論 0 288
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,933評(píng)論 1 334
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,772評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,973評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,516評(píng)論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,209評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,638評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,866評(píng)論 1 285
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,644評(píng)論 3 391
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,953評(píng)論 2 373

推薦閱讀更多精彩內(nèi)容