二分查找又稱折半查找,它是一種效率較高的查找方法。算法
二分查找要求:線性表是有序表,即表中結點按關鍵字有序,而且要用向量做爲表的存儲結構。不妨設有序表是遞增有序的。性能
二、基本思想
spa
二分查找的基本思想是:指針
設R[low..high]是當前的查找區間code
(1)首先肯定該區間的中點位置:orm
(2)而後將待查的K值與R[mid].key比較:若相等,則查找成功並返回此位置,不然須肯定新的查找區間,繼續二分查找,具體方法以下:排序
① 若R[mid].key>K,則由表的有序性可知R[mid..n].keys均大於K,所以若表中存在關鍵字等於K的結點,則該結點一定是在位置mid左邊的子表R[1..mid-1]中,故新的查找區間是左子表R[1..mid-1]。ci
② 若R[mid].key<K,則要查找的K必在mid的右子表R[mid+1..n]中,即新的查找區間是右子表R[mid+1..n]。下一次查找是針對新的查找區間進行的。it
所以,從初始的查找區間R[1..n]開始,每通過一次與當前查找區間的中點位置上的結點關鍵字的比較,就可肯定查找是否成功,不成功則當前的查找區間就縮小一半。這一過程重複直至找到關鍵字爲K的結點,或者直至當前的查找區間爲空(即查找失敗)時爲止。io
二分查找只適用順序存儲結構。
/*折半查找*/ int Binary_Search(int a*,int n,int key) { int low,high,mid; low=1; /*定義最底下標爲記錄首位*/ high=n; /*定義最高下標爲記錄末位*/ while(low<=high) { mid=(low+high)/2; /*折半*/ if(key<a[mid]) high=mid-1; if(key>a[mid]) low=mid+1; else return mid; } return 0; }
也能夠以下構造參數:
int BinSearch(SeqList R,KeyType K) { //在有序表R[1..n]中進行二分查找,成功時返回結點的位置,失敗時返回零 int low=1; int high=n; int mid; //置當前查找區間上、下界的初值 while(low<=high) //當前查找區間R[low..high]非空 { mid=(low+high)/2; if(R[mid].key==K) return mid; //查找成功返回 if(R[mid].kdy>K) high=mid-1; //繼續在R[low..mid-1]中查找 else low=mid+1; //繼續在R[mid+1..high]中查找 } return 0; //當low>high時表示查找區間爲空,查找失敗 }
① 執行過程
設算法的輸入實例中有序的關鍵字序列爲
(05,13,19,21,37,56,64,75,80,88,92)
拓展:
二分查找斷定樹
二分查找過程可用二叉樹來描述:把當前查找區間的中間位置上的結點做爲根,左子表和右子表中的結點分別做爲根的左子樹和右子樹。由此獲得的二叉樹,稱爲描述二分查找的斷定樹(Decision Tree)或比較樹(Comparison Tree)。
注意:
斷定樹的形態只與表結點個數n相關,而與輸入實例中R[1..n].keys的取值無關。
(1)二分查找斷定樹的組成
①圓結點即樹中的內部結點。樹中圓結點內的數字表示該結點在有序表中的位置。
②外部結點:圓結點中的全部空指針均用一個虛擬的方形結點來取代,即外部結點。
③樹中某結點i與其左(右)孩子鏈接的左(右)分支上的標記"<"、"("、">"、")"表示:當待查關鍵字K<R[i].key(K>R[i].key)時,應走左(右)分支到達i的左(右)孩子,將該孩子的關鍵字進一步和K比較。若相等,則查找過程結束返回,不然繼續將K與樹中更下一層的結點比較。
(2)二分查找斷定樹的查找
二分查找就是將給定值K與二分查找斷定樹的根結點的關鍵字進行比較。若相等,成功。不然若小於根結點的關鍵字,到左子樹中查找。若大於根結點的關鍵字,則到右子樹中查找。
【例】對於有11個結點的表,若查找的結點是表中第6個結點,則只需進行一次比較;若查找的結點是表中第3或第9個結點,則需進行二次比較;找第1,4,7,10個結點須要比較三次;找到第2,5,8,11個結點須要比較四次。
因而可知,成功的二分查找過程剛好是走了一條從斷定樹的根到被查結點的路徑,經歷比較的關鍵字次數恰爲該結點在樹中的層數。若查找失敗,則其比較過程是經歷了一條從斷定樹根到某個外部結點的路徑,所需的關鍵字比較次數是該路徑上內部結點的總數。
【例】待查表的關鍵字序列爲:(05,13,19,21,37,56,64,75,80,88,92),若要查找K=85的記錄,所通過的內部結點爲六、九、10,最後到達方形結點"9-10",其比較次數爲3。
實際上方形結點中"i-i+1"的含意爲被查找值K是介於R[i].key和R[i+1].key之間的,即R[i].key<K<R[i+1].key。
② 二分查找的平均查找長度
設內部結點的總數爲n=2h-1,則斷定樹是深度爲h=lg(n+1)的滿二叉樹(深度h不計外部結點)。樹中第k層上的結點個數爲2k-1,查找它們所需的比較次數是k。所以在等機率假設下,二分查找成功時的平均查找長度爲:
ASLbn≈lg(n+1)-1
二分查找在查找失敗時所需比較的關鍵字個數不超過斷定樹的深度,在最壞狀況下查找成功的比較次數也不超過斷定樹的深度。即爲:
二分查找的最壞性能和平均性能至關接近。
③ 二分查找的優勢
折半查找的時間複雜度爲O(logn),遠遠好於順序查找的O(n)。
④ 二分查找的缺點
雖然二分查找的效率高,可是要將表按關鍵字排序。而排序自己是一種很費時的運算。既使採用高效率的排序方法也要花費O(nlgn)的時間。
⑤ 適用狀況
二分查找只適用順序存儲結構。爲保持表的有序性,在順序結構裏插入和刪除都必須移動大量的結點。所以,二分查找特別適用於那種一經創建就不多改動、而又常常須要查找的線性表。
對那些查找少而又常常須要改動的線性表,可採用鏈表做存儲結構,進行順序查找。鏈表上沒法實現二分查找。