1. 插值查找
(1)說明
在介紹插值查找之前,首先考慮一個新問題,為什么上述算法一定要是折半,而不是折四分之一或者折更多呢?
打個比方,在英文字典里面查“apple”,你下意識翻開字典是翻前面的書頁還是后面的書頁呢?如果再讓你查“zoo”,你又怎么查?很顯然,這里你絕對不會是從中間開始查起,而是有一定目的的往前或往后翻。
同樣的,比如要在取值范圍1 ~ 10000 之間 100 個元素從小到大均勻分布的數組中查找5, 我們自然會考慮從數組下標較小的開始查找。
經過以上分析,折半查找這種查找方式,不是自適應的(也就是說是傻瓜式的)。二分查找中查找點計算如下:
mid=(low+high)/2, 即mid=low+1/2*(high-low);
通過類比,我們可以將查找的點改進為如下:
mid=low+(key-a[low])/(a[high]-a[low])*(high-low),
也就是將上述的比例參數1/2改進為自適應的,根據關鍵字在整個有序表中所處的位置,讓mid值的變化更靠近關鍵字key,這樣也就間接地減少了比較次數。
(2)基本思想:
基於二分查找算法,將查找點的選擇改進為自適應選擇,可以提高查找效率。當然,差值查找也屬於有序查找。
注:對於表長較大,而關鍵字分布又比較均勻的查找表來說,插值查找算法的平均性能比折半查找要好的多。反之,數組中如果分布非常不均勻,那么插值查找未必是很合適的選擇。
(3)復雜度分析
查找成功或者失敗的時間復雜度均為O(log2(log2n))。
2.代碼
public static int insertionSearch(int a[], int value, int low, int high) { int mid = low + (value - a[low]) / (a[high] - a[low]) * (high - low); if (a[mid] == value) return mid; if (a[mid] > value) return insertionSearch(a, value, low, mid - 1); if (a[mid] < value) return insertionSearch(a, value, mid + 1, high); return -1; } public static void main(String[] args) { int[] a = {27,38,49,50,65,76,197,213};//必須是有序的 int num = insertionSearch(a, 213,0,a.length-1); System.out.println("數組的下標是:" + num); }