查找
本文為查找算法的第一部分內容,包括了基本概念,順序查找、二分查找和索引查找。關於散列表和B樹查找的內容,待有空更新吧。
基本概念
查找(search)又稱檢索,在計算機上對數據表進行查找,就是根據所給條件查找出滿足條件的第一條記錄(元素)或全部記錄。
若沒有找到滿足條件的記錄,則返回特定值,表明查找失敗;若查找到滿足條件的第一條記錄,則表明查找成功,通常要求返回該記錄的存儲位置或記錄值本身,以便進行進一步處理;若需要查找到滿足條件的所有記錄,則可看做在多個區間內連續查找到滿足條件的第一條記錄的過程,即首先在整個區間內查找到滿足條件的第一條記錄,接着在剩余的區間內查找滿足條件的第一條記錄,以此類推,直到剩余區間為空為止。
作為查找對象的表的結構不同,其查找方法一般也不同。
查找過程是關鍵字比較的過程,比較次數的多少就是相應算法的時間復雜度,它是衡量一個查找算法優劣的重要指標。
對於一個查找算法的時間復雜度,還可以采用平均查找長度(Average Search Length, ASL),即在查找成功情況下的平均比較次數來表示。
平均查找長度的計算公式為: ASL=∑pici
其中n為查找表的長度,即表中所含元素的個數,pi 為查找第i個元素的概率, ci為查找第i個元素時所需的比較次數。
若查找每個元素的概率相同,在具有n個元素的線性表上順序查找其關鍵字域的值等於K的元素時,ci=i ,所以平均查找長度為: ASL=(n+1)/2
順序表查找
順序表(sequential list)是指集合或線性表的順序存儲結構。
在順序表上進行查找主要有兩種方法:順序查找方法和二分查找方法。
順序查找
順序查找(sequential search)又稱線性查找,從順序表的一端開始,依次將每個元素的關鍵字同給定值K進行比較,若某個元素的關鍵字等於K,則表明查找成功,返回該元素下標,若所有元素都比較完畢仍找不到,則表明查找失敗,返回特定值,常用-1.
優點:最簡單,對元素排列次序無要求,插入新元素方便。
缺點:速度慢,平均查找長度為(n+1)/2,約為表長度一半。
提高效率的方法:按查找概率從大到小排列。事先未知概率的情況下,每次查找到一個元素時,將它與前驅元素對調位置,這樣,查找頻度高的元素就會逐漸前移。
二分查找
二分查找(binary search)又稱折半查找,對分查找。作為二分查找對象的數據表必須是順序存儲的有序表。
二分查找的過程:有序表A[0]~A[n-1],首先取中點元素A[mid]的關鍵字同給定值K進行比較,若相等則查找成功;否則,若K< A[mid].key,則在左子表中繼續進行二分查找;若K> A[mid].key,則在右子表中繼續進行二分查找;這樣,經過一次比較,就縮小一半查找空間,如此進行下去,直到查找成功,或者當前查找區間為空時為止(或區間的下界大於等於上界時為止)。
二分查找的過程是遞歸的,也很容易寫成非遞歸算法,只需要根據情況修改待查找區域的上下界即可。
二分查找過程可用一棵二叉樹來描述,樹中的每個根結點對應當前查找區間的中點元素,它的左子樹和右子樹分別對應該區間的左子表和右子表,通常把此樹稱為二分查找的判定樹。由於二分查找在有序表上進行,所以其對應的判定樹是一棵二叉搜索樹(排序樹)。
在有序表上二分查找一個關鍵字等於K的元素時,對應着判定樹中從根結點到待查結點的一條路徑,同關鍵字進行比較的次數就等於該路徑上的結點數,或者說等於待查結點的層數。
優點:時間復雜度為O(logn),查找速度快。
缺點:需要建立有序表,並且插入和刪除會比較麻煩。另外,只適用於順序存儲的有序表,不適用於鏈接存儲的有序表。
索引查找
索引的概念
索引查找(index search)又稱分級查找。
比如在查字典的時候,首先在部首表中查到對應檢字表中的頁碼,再在檢字表中根據字的筆畫數查到對應正文中的頁碼,最后在此頁碼中找到待查的漢字。其中,整個字典就是索引查找的對象,字典正文稱為主表,部首表、檢字表都是為方便查找主表而建立的索引,所以被稱為索引表。
檢字表以主表作為查找對象,所以稱檢字表為一級索引,稱部首表為二級索引,即對一級索引的索引。
在計算機中,索引查找是在集合或線性表的索引存儲結構的基礎上進行的。索引存儲的基本思想是:首先把主表按照一定的關系划分成若干個子表,為每個子表建立一個索引項,由所有的這些索引項構成主表的一個索引表,然后,可以采用順序或者鏈接的方式來存儲索引表和每個子表。
索引表中的每個索引項通常包含三個域(至少包含前兩個域):一是索引值域(index),用來存儲標識對應子表的索引值,相當於記錄的關鍵字;二是子表的開始位置域(start),用來存儲對應子表的第一個元素的存儲位置;三是子表長度域(length),用來存儲對應子表的元素個數。
在索引存儲中,若索引表中的每個索引項對應多條記錄,則稱為稀疏索引;若每個索引項唯一對應一條記錄,則稱為稠密索引。
索引查找算法
索引查找是在索引表和主表上進行的查找。
首先根據給定的索引值K1,在索引表上查找出索引值等於K1的索引項,以確定對應子表在主表中的開始位置和長度,然后再根據給定的關鍵字K2,在對應的子表中查找出關鍵字等於K2的元素。
索引查找的比較次數等於算法中查找索引表的比較次數和查找相應子表的比較次數之和。(下面的討論只考慮包含一級索引的情況)。
假定索引表長度為m,相應子表長度為s,則索引查找的平均查找長度為:
ASL =(1+m)/2+ (1+s)/2 = 1+ (m + s)/2
因為所有子表的長度之和等於主表長度n,所以若每個子表長度相同,即s=n/m,則平均查找長度為ASL =1+ (m + n/m)/2 。
由數學知識,當m=n/m時,平均長度最小,即 ASL= 1+n½。
可見,索引查找的速度快於順序查找,但低於二分查找。在主表被分為n½ 個子表的前提下,其時間復雜度為O(n½) 。
分塊查找
分塊查找(blocking search)屬於索引查找。它要求主表中每個子表(子表又稱為塊)之間是有序的(遞增或遞減)。
比如遞增,即前塊中的最大關鍵字必須小於后塊中的最小關鍵字。但每個塊中的元素排列次序可以是任意的。
它還要求索引表中的每個索引項的索引值域用來存儲對應塊中的最大關鍵字。
索引表是有序的,主表中的關鍵字域和索引表中的索引值域具有相同的數據類型,即為關鍵字所屬的類型。
由於索引表是有序的,所以在索引表上既可采用順序查找,又可采用二分查找,而每個塊中的記錄排列是任意的,所以在塊內只能采用順序查找。
關於散列查找和B樹查找的內容,有空的時候作為專題另講吧。