查找算法(二)插值查找

二分查找(折半查找)

它的前提是線性表中的記錄必須是有序的,線性表必須採用順序存儲。折半查找的基本思想是:在有序表中,取中間記錄做爲比較對象,若給定值與中間記錄的關鍵字相等,則查找成功;若給定值小於中間記錄的關鍵字,則在中間記錄的左半區繼續查找;若給定值大於中間記錄的關鍵字,則在中間記錄的右半區繼續查找。不斷重複上述過程,直到查找成功,或全部查找區域無記錄,查找失敗爲止。html

代碼實現
int BinarySearch(int a[], int value){ int n = a.length; int low = 0; int high = n-1; while(low <= high){ int mid = low + (high - low)/2; if(a[mid] == value){ return mid; } elseif(a[mid] > value){ high = mid -1; } else{ low = mid + 1; } } return -1; } 

遞歸版本編程

int BinarySearch(int a[], int value, int low, int high){ int mid = low + (high - low)/2; if(a[mid] == value){ return mid; } elseif(a[mid] > value){ return BinarySearch(a,value,low,mid - 1); }else{ return BinarySearch(a,value,mid + 1,high); } } 

時間複雜度:O(log(n))性能

注:折半查找的前提條件是須要有序順序存儲,對於靜態查找表,一次排序後再也不變化,折半查找能獲得不錯的效率。但對於須要頻繁執行插入或刪除操做的數據集來講,維護有序的排序會帶來不小的工做量,那就不建議使用了。spa

插值查找

基本思想:基於二分查找,將查找點的選擇改進爲自適應選擇,能夠提升查找效率。 將二分查找的插值計算公式改成code

mid = low + \tfrac{(value - a[low])}{(a[high] - a[low])}(high-low)mid=low+(a[high]a[low])(valuea[low])(highlow)

時間複雜度:平均狀況O(loglog(n)),最壞O(log(n))htm

注:對於表長較大,而關鍵字分佈又比較均勻的查找表來講,插值查找的平均性能比折半查找要好。對象

斐波那契查找

原理:斐波那契查找與折半查找很類似,他是根據斐波那契數列的特色對有序表進行分割的。他要求開始表中記錄的個數比某個斐波那契數小1,即n=F(K)-1;當記錄不知足時,後面的元素都賦值爲最後一個值。(注:使得n=F(K)-1是由於:若是表中的數據爲F(K)-1個,mid分割又用掉一個,剩下F(K)-2個,正好分給兩個子序列,每一個子序列的長度爲F(K-1)-1和F(K-2)-1,格式和以前的統一,方便遞歸編程實現)排序

mid = low + F(k-1) - 1mid=low+F(k1)1

將value值與第mid位置的記錄進行比較,比較結果分爲三種:遞歸

  1. 相等,則返回mid
  2. 大於,low = mid + 1low=mid+1,k = k - 2k=k2
  3. 小於,high = mid - 1high=mid1,k = k - 1k=k1

(說明:low=mid+1說明待查找的元素在[mid+1,high]範圍內,k-=2 說明範圍[mid+1,high]內的元素個數爲F(k-2)-1個)ci

代碼實現
int FibonacciSearch(int[] a, int value){ int[] F = {0,1,1,2,3,5,8,13,21,34,55}; int n, low, high, mid, k; n = a.length; low = 1; high = n; k = 0;//斐波那契數列的下標 while(n > F[k] - 1){//計算n位於斐波那契數列的位置 ++k; } //省略將a後移一位,而且長度擴展到F(k) for(int i = n + 1; i <= F[k] - 1; i++){//將不滿的數值補全,長度爲F(k) - 1 a[i] = a[n]; } while(low <= high){ mid = low + F[k - 1] - 1; if(value > a[mid]){ low = mid + 1; k = k - 2;//mid右邊的個數,即F[k-2]個 }elseif(value < a[mid]){ high = mid - 1; k = k - 1;//mid左邊的個數 }else{ if(mid < n){ return mid; }else{ return n; } } } return -1; } 

總結: 平均性能平均性能:斐波那契>折半>插值

由於折半查找進行加法與除法運算(mid = (low + high) / 2),插值查找進行復雜的四則運算( mid = low + (key - a[low] / (a[high] - a[low]) * (high - low)) ),而斐波那契查找只是運用簡單加減法運算 (mid = low + f[k-1] -1) ,在海量的數據查找過程當中,這種席位的差異會影響最終的查找效率。三種有序表的查找本質上是分割點的選擇不一樣,各有優劣,實際開發可根據數據的特色綜合考慮再作決定。

相關文章
相關標籤/搜索