/**
*
* @author jiadongkai
* @date Dec 2, 2011
*
*/
public class BinSearch {
/**
* 有序数组[1,2,3,4,5]
* 折半查找arr数组中num的index,不存在返回-1
* @param arr
* @param num
* @return
*/
public static int binSearch(int[] arr, int num){
int low = 0, high = arr.length-1;
int mid = 0;
while(low <= high){
count++;
mid = (low+high)/2;
if(arr[mid] == num) return mid;
if(arr[mid] < num)//合适的位置在后半部分
low = mid + 1;
else //合适的位置在前半部分
high = mid - 1;
}
return -1;
}
static int count ;
/**
* [1,2,3,4,5]->[4,5,1,2,3]
* 在倒置的数组中查找一个元素
*
* 选取mid之后,前后必有一半是有序的。比较low/mid-1和mid+1/high
* 这两对位置的值就知道
* 如果num落在有序的一半,
* 接下来的查找都变成折半查找;如果num落在无序的一半,
* @param arr
* @param num
* @return
*/
public static int exBinSearch(int arr[], int num){
int low = 0, high = arr.length-1;
int mid = 0;
//用于标记num是否已经进入有序那一半
//若进入,则下次直接使用折半查找的逻辑
boolean flag = false;
while(low <= high){
count++;
mid = (low + high)/2;
if(arr[mid] == num) return mid;
if( !flag && (arr[low] <= arr[mid-1])){
//若前半部分有序
if((arr[low] <= num) && (num <= arr[mid-1])){
//若num落在有序的前半部分
System.out.println("进入有序数组:"+(low)+" -> "+(mid-1));
flag = true;
high = mid -1;
}else{
//若num落在后半部分
low = mid + 1;
}
continue;
}
if( !flag && arr[mid+1] <= arr[high]){
//若后半部分有序
if( (arr[mid+1] <= num) && (num <= arr[high])){
//若num落在有序的后半部分
System.out.println("进入有序数组:"+(mid+1)+" -> "+high);
flag = true;
low = mid+1;
}else{
//若num落在无序的前半部分
high = mid - 1;
}
continue;
}
//能运行下面的逻辑,必然是已经确定num落在有序的部分了
if( arr[mid] < num )
low = mid + 1;
else
high = mid - 1;
}
return -1;
}
public static void main(String args[]){
int arr[] = {1,3,5,6,7,8,9,10,22,34,56,67,89,100};
int arr2[] = {67,89,100,1,3,5,6,7,8,9,10,22,34,56};
int demo[] = {1,3,5,11,100,56,90,1000};
for(int i : demo){
System.out.println("---------比较i="+i+"-------------");
System.out.println( i + "的index:" + binSearch(arr, i) );
System.out.println("比较次数:"+count);
count=0;
System.out.println( i + "的index:" + exBinSearch(arr2, i));
System.out.println("比较次数:"+count);
}
}
}
//~~~~
---------比较i=1-------------
1的index:0
比较次数:3
进入有序数组:3 -> 3
1的index:3
比较次数:4
---------比较i=3-------------
3的index:1
比较次数:8
3的index:4
比较次数:3
---------比较i=5-------------
5的index:2
比较次数:5
5的index:5
比较次数:4
---------比较i=11-------------
11的index:-1
比较次数:8
进入有序数组:7 -> 13
11的index:-1
比较次数:4
---------比较i=100-------------
100的index:13
比较次数:8
100的index:2
比较次数:2
---------比较i=56-------------
56的index:10
比较次数:4
进入有序数组:7 -> 13
56的index:13
比较次数:4
---------比较i=90-------------
90的index:-1
比较次数:8
90的index:-1
比较次数:4
---------比较i=1000-------------
1000的index:-1
比较次数:8
1000的index:-1
比较次数:4