大二數據結構第八次總結----查找

                                                 查找

1.查找的基本概念

列表:由同一類型的數據元素組成的集合。

關鍵碼:數據元素中的某個數據項,可以標識列表中的一個或一組數據元素。 

鍵值:關鍵碼的值。

主關鍵碼:可以唯一地標識一個記錄的關鍵碼。

次關鍵碼:不能唯一地標識一個記錄的關鍵碼。

查找 :在具有相同類型的記錄構成的集合中找出滿足給定條件的記錄。 

查找的結果 :若在查找集合中找到了與給定值相匹配的記錄,則稱查找成功;否則,稱查找失敗。 

靜態查找 :不涉及插入和刪除操作的查找 。

動態查找 :涉及插入和刪除操作的查找。 

靜態查找適用於:查找集合一經生成,便只對其進行查找,而不進行插入和刪除操作; 或經過一段時間的查找之後,集中地進行插入和刪除等修改操作;

動態查找適用於:查找與插入和刪除操作在同一個階段進行,例如當查找成功時,要刪除查找到的記錄,當查找不成功時,要插入被查找的記錄。

查找結構 :面向查找操作的數據結構 ,即查找基於的數據結構。

線性表:適用於靜態查找,主要採用順序查找技術、折半查找技術。

樹表:適用於動態查找,主要採用二叉排序樹的查找技術。

散列表:靜態查找和動態查找均適用,主要採用散列技術。 

 

 

2.順序查找 (線性查找)

基本思想:

從線性表的一端向另一端逐個將關鍵碼與給定值進行比較,

若相等,則查找成功,給出該記錄在表中的位置;

若整個表檢測完仍未找到與給定值相等的關鍵碼,則查找失敗,給出失敗信息。

int LineSearch :: SeqSearch(int k)

{  

     i=n;

     while (i>0 && data[i]!=k)

         i--;

     return i;

}

3.順序查找有哨兵

基本思想:設置“哨兵”。

哨兵就是待查值,

將哨兵放在查找方向的盡頭處,

免去了在查找過程中每一次比較後都要判斷查找位置是否越界,從而提高查找速度。

4.順序查找的優點:

算法簡單而且使用面廣。

對錶中記錄的存儲結構沒有任何要求,順序存儲和鏈接存儲均可;

對錶中記錄的有序性也沒有要求,無論記錄是否按關鍵碼有序均可。

5.順序查找的缺點:

平均查找長度較大,特別是當待查找集合中元素較多時,查找效率較低

6.折半查找

適用條件:

線性表中的記錄必須按關鍵碼有序;

必須採用順序存儲。

基本思想:

在有序表中(low, high,low<=high),

取中間記錄作爲比較對象,

若給定值與中間記錄的關鍵碼相等,則查找成功;

若給定值小於中間記錄的關鍵碼,則在中間記錄的左半區繼續查找;

若給定值大於中間記錄的關鍵碼,則在中間記錄的右半區繼續查找。

不斷重複上述過程,直到查找成功,或所查找的區域無記錄,查找失敗。

折半查找判定樹

判定樹:折半查找的過程可以用二叉樹來描述,

樹中的每個結點對應有序表中的一個記錄,

結點的值爲該記錄在表中的位置。

通常稱這個描述折半查找過程的二叉樹爲折半查找判定樹,簡稱判定樹。

⑴ 當n=0時,折半查找判定樹爲空;

⑵ 當n>0時,

  折半查找判定樹的根結點爲mid=(n+1)/2,

  根結點的左子樹是與有序表r[1] ~ r[mid-1]相對應的折半查找判定樹,

  根結點的右子樹是與r[mid+1] ~ r[n]相對應的折半查找判定樹。

判定樹的特點

任意兩棵折半查找判定樹,若它們的結點個數相同,則它們的結構完全相同

具有n個結點的折半查找樹的高度爲

判定樹的性質

任意結點的左右子樹中結點個數最多相差1

任意結點的左右子樹的高度最多相差1

任意兩個葉子所處的層次最多相差1

折半查找性能分析

具有n個結點的折半查找判定樹的深度爲

查找成功:在表中查找任一記錄的過程,即是折半查找判定樹中從根結點到該記錄結點的路徑,和給定值的比較次數等於該記錄結點在樹中的層數。

查找不成功:

查找失敗的過程就是走了一條從根結點到外部結點的路徑,

和給定值進行的關鍵碼的比較次數等於該路徑上內部結點的個數(失敗情況下的平均查找長度等於樹的高度)。

線性表查找的特點

線性表查找是靜態的查找,要在線性表上進行動態查找,存在以下的問題

無序順序表上進行動態查找,插入操作簡單,但查找的複雜性高

有序順序表上進行動態查找,查找的時間複雜性好,但是插入操作時間複雜性高

單鏈表上進行動態查找,插入操作簡單,但查找操作複雜性高

解決辦法:             

採用二叉樹這種數據結構,實現動態查找

二叉排序樹(Binary Search Tree)

二叉排序樹(也稱二叉查找樹):或者是一棵空的二叉樹,或者是具有下列性質的二叉樹:

⑴若它的左子樹不空,則左子樹上所有結點的值均小於根結點的值;

⑵若它的右子樹不空,則右子樹上所有結點的值均大於根結點的值;

⑶ 它的左右子樹也都是二叉排序樹。

二叉排序樹的插入

分析:若二叉排序樹爲空樹,則新插入的結點爲新的根結點;否則,新插入的結點必爲一個新的葉子結點,其插入位置由查找過程得到。

若二叉排序樹爲空樹,則新插入的結點爲新的根結點;

否則,如果插入的值比根節點值大,則在右子樹中進行插入;否則,在左子樹中進行插入。

遞歸。

二叉排序樹的構造

從空的二叉排序樹開始,依次插入一個個結點 。

二叉排序樹的刪除

在二叉排序樹上刪除某個結點之後,仍然保持二叉排序樹的特性。

分三種情況討論:

被刪除的結點是葉子;
被刪除的結點只有左子樹或者只有右子樹;
被刪除的結點既有左子樹,也有右子樹。
二叉排序樹的刪除算法——僞代碼

若結點p是葉子,則直接刪除結點p;
2. 若結點p只有左子樹,   則只需重接p的左子樹;

    若結點p只有右子樹,  則只需重接p的右子樹;

3. 若結點p的左右子樹均不空,則

   3.1 查找結點p的右子樹上的最左下結點s及s雙親結點par;

   3.2 將結點s數據域替換到被刪結點p的數據域;

   3.3 若結點p的右孩子無左子樹,

         則將s的右子樹接到par的右子樹上;

若結點p是葉子,則直接刪除結點p;
2. 若結點p只有左子樹,則只需重接p的左子樹;

    若結點p只有右子樹,則只需重接p的右子樹;

3. 若結點p的左右子樹均不空,則

   3.1 查找結點p的右子樹上的最左下結點s及s雙親結點par;

   3.2 將結點s數據域替換到被刪結點p的數據域;

   3.3 若結點p的右孩子無左子樹,

         則將s的右子樹接到par的右子樹上;

         否則,將s的右子樹接到結點par的左子樹上;

   3.4 刪除結點s;

二叉排序樹的查找

在二叉排序樹中查找給定值k的過程是:

⑴ 若root是空樹,則查找失敗;

⑵ 若k=root->data,則查找成功;否則

⑶ 若k<root->data,則在root的左子樹上查找;否則

⑷ 在root的右子樹上查找。

     上述過程一直持續到k被找到或者待查找的子樹爲空,如果待查找的子樹爲空,則查找失敗。

二叉排序樹的查找效率在於只需查找二個子樹之一。

平衡二叉樹(AVL樹)

平衡二叉樹:或者是一棵空的二叉排序樹,或者是具有下列性質的二叉排序樹:

⑴ 根結點的左子樹和右子樹的深度最多相差1;

⑵ 根結點的左子樹和右子樹也都是平衡二叉樹。

 

平衡因子:結點的平衡因子是該結點的左子樹的深度與右子樹的深度之差。

最小不平衡子樹:在平衡二叉樹的構造過程中,以距離插入結點最近的、且平衡因子的絕對值大於1的結點爲根的子樹。

基本思想:

在構造二叉排序樹的過程中,每插入一個結點時,首先檢查是否因插入而破壞了樹的平衡性,

若是,

  則找出最小不平衡子樹,

  在保持二叉排序樹特性的前提下,調整最小不平衡子樹中各結點之間的鏈接關係,進行相應的旋轉,使之成爲新的平衡子樹。

樹表的查找技術

B-樹

m階B-樹:是滿足下列特性的樹:

樹中每個結點至多有m棵子樹;
(2) 若根結點不是終端結點,則至少有兩棵子樹;

除根結點外,其他非終端結點至少有ém/2ù 棵子樹;
(4)所有非終端結點都包含以下數據:

    (n,A0,K1,A1,K2,…,Kn,An)

n(ém/2ù -1≤n≤m -1)爲關鍵碼的個數;
      Ki(1≤i≤n)爲關鍵碼,且Ki<Ki+1(1≤i≤n-1);

      Ai(0≤i≤n)爲指向子樹根結點的指針,且指針Ai所指子樹中所有結點的關鍵碼均小於Ki+1大於Ki。

(5)所有葉子結點都在同一層上,B樹是高平衡的。

B-樹的插入    

基本原理:

當一個節點中插入新的數據時,
會造成節點中數據個數大於(m-1),
此時需要分裂節點,
將節點中第[m/2]+1個數據插入到當前節點的前驅中,
當前節點分裂爲兩個節點。
刪除小結: 在B-樹最下層節點中刪除一個關鍵字

當最下層結點中的關鍵字數大於ém/2ù -1 時,可直接刪除。
當最下層待刪關鍵字所在結點中關鍵字數目爲最低要求ém/2ù -1時,如果其左(右)兄弟中關鍵字數目大於ém/2ù -1,則可採用“父子換位法”。
當最下層待刪結點及其左右兄弟中的關鍵字數目均爲最低要求數目ém/2ù -1時,需要進行合併處理,合併過程與插入時的分裂過程“互逆”,合併一次, 分支數少一,可能出現 “連鎖合併”, 當合併到根時, 各分支深度同時減1。
在B-樹中刪除一個關鍵字-非最下層節點中刪除

基本原則:在保持有序性、平衡性的前提下,進行操作

B+樹的結構定義

m階B+樹的結構定義如下:

 (1)每個結點至多有m個子結點;

(2)每個結點(除根外)至少有ceiling(m/2)個子結點;

(3)根結點至少有兩個子結點;

(4)有k個子結點的結點必有k個關鍵碼。

B+樹

m階B+樹:是滿足下列特性的樹:

⑴ 含有m個關鍵碼,每一個關鍵碼對應一棵子樹。

⑵ 關鍵碼Ki是它所對應的子樹的根結點中的最大(或最小)關鍵碼。

⑶ 所有終端結點中包含了全部關鍵碼信息,以及指向關鍵碼記錄的指針。

⑷ 所有終端結點按關鍵碼的大小鏈在一起,形成單鏈表,並設置頭指針。

B+樹的查找

查找應該到葉結點層

在上層已找到待查的關鍵碼,並不停止

而是繼續沿指針向下一直查到葉結點層的這個關鍵碼

 B+樹的葉結點一般鏈接起來,形成一個雙鏈表

適合順序檢索(範圍檢索)

B-樹和B+樹

特點

對於階數相同的兩棵樹,每個節點所包含的分支數的定義相同(不能少於m/2,不能多於m)

每個節點所包含的關鍵字的個數不同

B-樹中,關鍵字不重複出現;B+樹中,葉子節點存放所有的關鍵字,內部結點存儲着其後繼節點中最大的關鍵字

插入操作都會引起節點的分裂

刪除操作都會引起節點的合併

B-樹適用於隨機檢索;B+樹支持隨機和順序檢索

散列表(hash)的查找技術

散列函數的構造

直接定址法

除留餘數法

數字分析法

平方取中法

摺疊法(分段疊加法)

衝突處理方法

開放定址法

鏈地址法

建立公共溢出區

散列的基本思想:在記錄的存儲地址和它的關鍵碼之間建立一個確定的對應關係。這樣,不經過比較,一次讀取就能得到所查元素的查找方法。

散列表:採用散列技術將記錄存儲在一塊連續的存儲空間中,這塊連續的存儲空間稱爲散列表。

散列函數:將關鍵碼映射爲散列表中適當存儲位置的函數。

散列地址:由散列函數所得的存儲位置址 。

散列技術一般不適用於允許多個記錄有同樣關鍵碼的情況。
有衝突,降低了查找效率,體現不出計算式查找的優點
散列方法也不適用於範圍查找
不能查找最大值、最小值
也不可能找到在某一範圍內的記錄。
 

散列技術的關鍵問題:

⑴ 散列函數的設計。如何設計一個簡單、均勻、存儲利用率高的散列函數。

⑵ 衝突的處理。如何採取合適的處理衝突方法來解決衝突。

衝突:對於兩個不同關鍵碼ki≠kj,有H(ki)=H(kj),即兩個不同的記錄需要存放在同一個存儲位置,ki和kj相對於H稱做同義詞。

設計散列函數一般應遵循以下原則:

⑴ 計算簡單。散列函數不應該有很大的計算量,否則會降低查找效率。

⑵ 函數值即散列地址分佈均勻。函數值要儘量均勻散佈在地址空間,這樣才能保證存儲空間的有效利用並減少衝突

散列函數是關鍵碼的線性函數,即:

(key) = a ´ key + b  (a,b爲常數)
散列函數爲:

H(key)=key  mod  p

散列函數——除留餘數法

一般情況下,選p爲小於或等於表長(最好接近表長)的最小素數

散列函數——數字分析法

根據關鍵碼在各個位上的分佈情況,選取分佈比較均勻的若干位組成散列地址。

適用情況:

事先知道關鍵碼的分佈,

關鍵碼的分佈均勻

散列函數——平方取中法

對關鍵碼平方後,按散列表大小,取中間的若干位作爲散列地址(平方後截取)。

適用情況:
事先不知道關鍵碼的分佈且關鍵碼的位數不是很大。

散列函數——摺疊法

將關鍵碼從左到右分割成位數相等的幾部分,將這幾部分疊加求和,取後幾位作爲散列地址。

關鍵碼位數很多,事先不知道關鍵碼的分佈。

處理衝突的方法——開放定址法

由關鍵碼得到的散列地址一旦產生了衝突,就去尋找下一個空的散列地址,並將記錄存入。

如何尋找下一個空的散列地址?

(1)線性探測法

(2)二次探測法

(3)隨機探測法

(4)再hash法

用開放定址法處理衝突得到的散列表叫閉散列表。

線性探測法

當發生衝突時,從衝突位置的下一個位置起,依次尋找空的散列地址。

對於鍵值key,設H(key)=d,閉散列表的長度爲m,則發生衝突時,尋找下一個散列地址的公式爲:

      Hi=(H(key)+di) % m   (di=1,2,…,m-1)

二次探測法

當發生衝突時,尋找下一個散列地址的公式爲:

                     Hi=(H(key)+di)% m

(di=12,-12,22,-22,…,q2,-q2且q≤m/2)

隨機探測法

當發生衝突時,下一個散列地址的位移量是一個隨機數列,即尋找下一個散列地址的公式爲:

                         Hi=(H(key)+di)% m   

(di是一個隨機數列,i=1,2,……,m-1)

處理衝突的方法——拉鍊法(鏈地址法)

基本思想:將所有散列地址相同的記錄,即所有同義詞的記錄存儲在一個單鏈表中(稱爲同義詞子表),在散列表中存儲的是所有同義詞子表的頭指針。

用拉鍊法處理衝突構造的散列表叫做開散列表。

處理衝突的方法——公共溢出區

基本思想:

散列表包含基本表和溢出表兩部分(通常溢出表和基本表的大小相同),

將發生衝突的記錄存儲在溢出表中。

查找時,對給定值通過散列函數計算散列地址,先與基本表的相應單元進行比較,若相等,則查找成功;否則,再到溢出表中進行順序查找。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章