算法思路:
1.由数组的左右边界生成中间节点。
2.判断中间节点的值和需要查找的数值是否一致。
3.不断调节mid位置,递归的进行二分查找。
4.1查找到相等的值时,返回其下标。
4.2对于扩展二分,查找到数值时,向mid左侧遍历,如果还有此值,将此下标放入ArrayList中,然后将mid下标放入ArrayList,然后向mid右侧遍历,如果还有此值,将此下标放入ArrayList中,最后返回ArrayList。
插值查找:
插值查找适用于数据量较为庞大的有序且较为均匀的数组,利用基于二分查找加上自适应的方法查找:
利用自适应公式:
在递归出口判断处加上如下判断,一方面是为了防止进行不合法的搜索,另一方面也是为了防止之后利用上述公式计算时数组越界(value可能是一个很大的值,加入乘法计算很危险):
算法代码:
如下的quickSort函数为上一篇博客写的快速排序,将数组排序后,再进行二分查找。
以下为两种二分查找。
插值查找只需要将mid计算公式换成上述自适应公式,并且修改递归出口条件即可。
public class BinarySearch {
public static void main(String[] args) {
QuickSort qs = new QuickSort();
int[] arr = {5,43,56,6,8,20,1};
int[] arr2 = {5,43,56,6,5,20,5};
//对两个数组进行排序
qs.quickSort(arr, 0, 6);
for(int i = 0; i < arr.length; i++){
System.out.print(arr[i]+" ");
}
System.out.println();
qs.quickSort(arr2, 0, 6);
for(int i = 0; i < arr.length; i++){
System.out.print(arr2[i]+" ");
}
System.out.println();
System.out.println(binarySearch(arr, 0, 6, 43));//调用第一个二分查找的函数
System.out.println(binarySearch2(arr2, 0, 6, 5));//调用第二个二分查找的函数,针对查找有重复的数字
}
public static int binarySearch(int[] arr, int left, int right, int findVal){
if(left > right) return -1;
int mid = (left + right) / 2;
int midVal = arr[mid];
if(findVal > midVal){
return binarySearch(arr, mid + 1, right, findVal);
}
else if(findVal < midVal){
return binarySearch(arr, left, mid -1, findVal);
}
else{
return mid;
}
}
//扩展版二分,返回多个要查找的数的下标
public static ArrayList<Integer> binarySearch2(int[] arr, int left, int right, int findVal){
if(left > right) return new ArrayList<Integer>();
int mid = (left + right) / 2;
int midVal = arr[mid];
if(findVal > midVal){
return binarySearch2(arr, mid + 1, right, findVal);
}
else if(findVal < midVal){
return binarySearch2(arr, left, mid -1, findVal);
}
else{
/*思路分析:再找到mid索引值的时候,不要马上返回
先向mid左侧扫描,将满足查找值的元素下标放入ArrayList
然后向mid右侧扫描,将满足查找值的元素下标放入ArrayList
将ArrayList返回
*/
ArrayList<Integer> resIndexlist = new ArrayList<>();
int temp = mid -1;
while (true) {
if(temp < 0 || arr[temp] != findVal){//退出
break;
}
//否则,就temp放入到resIndexlist
resIndexlist.add(temp);
temp --;
}
resIndexlist.add(mid);
temp = mid + 1;
while (true) {
if(temp > arr.length - 1 || arr[temp] != findVal){//退出
break;
}
//否则,就temp放入到resIndexlist
resIndexlist.add(temp);
temp ++;
}
return resIndexlist;
}
}
}