首先声明一个概念:查找的基本方法可以分为两大类,即比较式查找法和计算机式。其中比较式查找法有可以分为基于线性表的查找法和基于树的查找法,而计算查找法也称为也称为HASH(哈希)查找法。
而基于线性表的查找法具体可分为顺序查找法、折半查找法以及分块查找法
现在要讲的就是折半查找法(二分查找法、二叉判定数查找法)
折半查找,也称二分查找、二分搜索,是一种在有序数组中查找某一特定元素的搜索算法。搜素过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜素过程结束;如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。如果在某一步骤数组已经为空,则表示找不到指定的元素。这种搜索算法每一次比较都使搜索范围缩小一半,其时间复杂度是O(logN)。
注意的是计算中间位置时不应该使用(high + low) / 2的方式,因为加法运算可能导致整数越界,这里应该使用以下三种方式之一:low + (high – low) / 2或low + (high – low) >> 1或(low + high) >>> 1(>>>是逻辑右移,是不带符号位的右移)。
递归实现:
public class BinSrch {
public static void main(String[] args) {
int[] data = { 12, 16, 19, 22, 25, 32, 39, 39, 48,
55, 57,58,63, 68, 69, 70, 78, 84, 88, 90, 97 };
while(true){
Scanner scanner = new Scanner(System.in);
int k = scanner.nextInt();
int low = 0;
int high= data.length-1;
int result = binarySearch2(data, low, high, k);
if(result == -1){
System.out.println("顺序表中没有"+k);
}else{
System.out.println(k+"在顺序表中的位置:"+result);
}
}
}
//递归
public static int binarySearch2(int[] data, int low, int high, int k){
if(low <= high){
int mid = low + ((high - low) >>> 1);
if(data[mid] == k){
return mid+1;
}else if(data[mid] < k){
return binarySearch2(data, mid+1, high, k);
}else{
return binarySearch2(data, low, mid-1, k);
}
}
return -1;
}
}
非递归实现:
public class BinSrch {
public static void main(String[] args) {
int[] data = { 12, 16, 19, 22, 25, 32, 39, 39, 48,
55, 57,58,63, 68, 69, 70, 78, 84, 88, 90, 97 };
while(true){
Scanner scanner = new Scanner(System.in);
int k = scanner.nextInt();
int result = binarySearch(data, k);
if(result == -1){
System.out.println("顺序表中没有"+k);
}else{
System.out.println(k+"在顺序表中的位置:"+result);
}
}
}
//非递归
public static int binarySearch(int[] data, int k){
int low = 0;
int high = data.length-1;
while(low <= high){
int mid = (low + high)>>>1;
if(data[mid] == k){
return mid + 1;
}
if(data[mid] > k){
high = mid-1;
}else{
low = mid +1;
}
}
return -1;
}
}