最基本的查找方法就是顺序查找与二分查找,二分查找可以进一步优化为插值查找
顺序查找
最简单的查找方法,逐个比较过来
public static int seqSearch(int[] arr, int key){
for (int i=0; i<arr.length; i++){
if (key == arr[i])
return i;
}
return -1;
}
二分查找
针对已经有序的数组,可以使用二分查找,又称折半查找
public static int binarySearch(int[] arr, int key){
int low =0;
int high = arr.length -1;
while(low <= high){
int mid = (low + high)/2;
++bcount;
if (key>arr[mid]) {
low = mid + 1;
} else if (key ==arr[mid]){
return mid;
} else {
high = mid -1;
}
}
return -1;
}
插值查找
在折半查找中, mid = (low + high)/2 = low + (high - low)/2,我们将右边的1/2替换为 (key-arr[low])/(arr[high]-arr[low])
- 当key ==arr[low]的时候 mid = low, mid往最左边移动
- 当key== arr[high]的时候, mid=high, mid往最右边活动
可见这是一种更聪明更有倾向性的查找方法
public static int chazhiSearch(int[] arr, int key){
int low =0;
int high = arr.length -1;
while(low <= high){
++ccount;
int mid = low + ((key-arr[low])*(high-low)/(arr[high]-arr[low]));
if (key>arr[mid]) {
low = mid + 1;
} else if (key ==arr[mid]){
return mid;
} else {
high = mid -1;
}
}
return -1;
}
测试代码
public static void main(String[] args) {
int[] array = new int[]{1,2,3,4,5,6,8,9,12,15,18,20};
assert(seqSearch(array, 9) == 7);
assert(seqSearch(array, 8)== -1);
System.out.println(binarySearch(array, 18));
System.out.println(chazhiSearch(array, 18));
System.out.println("bcount: " + bcount);
System.out.println("ccount: " + ccount);
}
运行结果:
10
10
bcount: 3
ccount: 2
对于这种分布比较均匀的数列,插值查找的次数要比二分查找少