对于已经排好序的表,有
1、折半查找
在有序表中,取中间的记录进行比较,如果相同,匹配成功。如果比中间值小,就在中间记录的左半区进行查找,如果大,就在右半区。
public static int binarySearch(int key){
int height = src.length-1;
int low = 0;
int mid = 0;
while(low <= height) {
mid = (height+low)/2;//对下标取半
if(key < src[mid]) //如果比中间值小,改变height的值
height = mid-1;
else if(key > src[mid])//如果比中间值大,改变low的值
low = mid+1;
else
return mid;
}
return -1;
}
2、插值查找
插值查找是对折半查找的改进。
折半时 mid =
(low+height)2
=
low2
+
height2
= low-
low2
+
height2
= low+
12
(height-low)
折半查找是按1/2进行查找,如果有10000个有序数组找一个很小的数5,就有了优化的空间。
将查mid的公式替换为mid=low+
key−a[low]a[height]−a[low]
(height-low) 即按比例获取要比较的中间值
3、斐波那契查找
斐波那契相邻的数接近黄金分割,与折半类似,只是切割的范围为黄金分割点。平均效率高于折半,最坏的效率比折半差
public static void main(String[] args) {
int[] src = { 1, 5, 15, 22, 25, 31, 39, 42, 47, 49, 59, 68, 88 };
System.out.println("==>" + FBSearch(src, 88));
}
public static int FBSearch(int array[], int key){
int mid,k=0;
int fibon[] = getFibon(20);//构建斐波那契数组
while(array.length > fibon[k]-1) //查找比数组长度大的斐波那契数
++k;
int tmp[] = Arrays.copyOf(array, fibon[k]-1);//将原数组长度扩展为斐波那契数的长度
for (int i = array.length; i < tmp.length; i++) //将扩展的部分填充为原数组最后一个数据
tmp[i] = array[array.length-1];
int low = 0;
int high = fibon[k]-1;
while(low <= high) {
mid = low + fibon[k-1]-1;
if(key < tmp[mid]) {
high = mid-1;
k -= 1;
} else if (key > tmp[mid]) {
// 查找后半部分,高位指针移动
low = mid+1;
// (全部元素) = (前半部分)+(后半部分)
// f[k] = f[k-1] + f[k-2]
// 因为后半部分有f[k-2]个元素,所以 k = k-2
k -= 2;
} else {
return mid<=array.length?mid:array.length;//如果mid大于原数组长度,则表示是原数组的最后一个
}
}
return -1;
}
//获取斐波那契数组
public static int[] getFibon(int len){
int fibon[] = new int[len];
fibon[0] = fibon[1] = 1;
for (int i = 2; i < len; i++) {
fibon[i] = fibon[i-1] + fibon[i-2];
}
return fibon;
}
参考:大话数据结构