插值查找

1)插值查找原理介绍: 插值查找算法类似于二分查找,不同的是插值查找每次从自适应 mid 处开始查找。
2)将折半查找中的求 mid 索引的公式 :

(low 表示左边索引 left, high 表示右边索引 right;key 就是前面我们讲的findVal)

3)int mid = low + (high - low) * (key - arr[low]) / (arr[high] - arr[low]); /*插值索引*/
对应前面的代码公式:
int mid = left + (right – left) * (findVal – arr[left]) / (arr[right] – arr[left])
4)举例说明插值查找算法 1-100 的数组:

插值查找注意事项:
  1) 对于数据量较大,关键字分布比较均匀的查找表来说,采用插值查找, 速度较快.。
  2) 关键字分布不均匀的情况下,该方法不一定比折半查找要好。

代码实现

1. public class insertvaluesearch {  
2.     public static void main(String[] args) {  
3.         Integer[] arr = {45, 56, 22, 11, 123, 456, 898, 562, 121, 45, 20, 320, 112, 123};//无序数组  
4.         //注意:使用插值查找的前提也是 该数组是有序的.  
5.   
6.        /*//降序排列方法: 
7.         Arrays.<Integer>sort(arr, new Comparator<Integer>() { 
8.             @Override 
9.             public int compare(Integer o1, Integer o2) { 
10.                 return Integer.compare(o2, o1); 
11.             } 
12.         });*/  
13.         Arrays.sort(arr);//升序排序  
14.         System.out.println("数组有序化后结果:" + Arrays.toString(arr));  
15.         //arr = {11, 20, 22, 45, 45, 56, 112, 121, 123, 123, 320, 456, 562, 898};  
16.   
17.         int search = insertVauleSearch(arr, 0, arr.length - 1, 45);  
18.         List<Integer> searchAll = insertValueSearchAll(arr, 0, arr.length - 1, 45);  
19.         System.out.println(search);  
20.         System.out.println(searchAll);  
21.     }  
22.   
23.     private static List<Integer> insertValueSearchAll(Integer[] arr, int left, int right, int findVal) {  
24.         if (left > right || findVal < arr[0] || findVal > arr[arr.length - 1]) {  
25.             return null;  
26.         } else {  
27.             int mid = left + (right - left) * (findVal - arr[left]) / (arr[right] - arr[left]);  
28.             if (findVal < arr[mid]) {  
29.                 return insertValueSearchAll(arr, left, mid - 1, findVal);  
30.             } else if (findVal > arr[mid]) {  
31.                 return insertValueSearchAll(arr, mid + 1, right, findVal);  
32.             } else {  
33.                 ArrayList<Integer> list = new ArrayList<>();  
34.                 list.add(mid);  
35.                 int t = mid - 1;  
36.                 while (true) {  
37.                     if (t < 0 || arr[t] != findVal) {  
38.                         break;  
39.                     } else {  
40.                         list.add(t);  
41.                         t--;  
42.                     }  
43.                 }  
44.                 t = mid + 1;  
45.                 while (true) {  
46.                     if (t > arr.length - 1 || arr[t] != findVal) {  
47.                         break;  
48.                     } else {  
49.                         list.add(t);  
50.                         t++;  
51.                     }  
52.                 }  
53.                 return list;  
54.             }  
55.         }  
56.     }  
57.   
58.     private static int insertVauleSearch(Integer[] arr, int left, int right, int findVal) {  
59.         //  当 left > right 时,说明递归整个数组,但是没有找到  
60.         //注意:findVal < arr[0]    和   findVal > arr[arr.length - 1] 必须需要  
61.         //否则我们得到的 mid 可能越界(例如当findVal无穷大,则mid也为无穷大,则arr角标越界)  
62.         if (left > right || findVal < arr[0] || findVal > arr[arr.length - 1]) {  
63.             return -1;  
64.         } else {  
65.             //  求出 mid, 自适应  
66.             int mid = left + (right - left) * (findVal - arr[left]) / (arr[right] - arr[left]);  
67.             if (findVal < arr[mid]) {//  说明向左递归查找  
68.                 return insertVauleSearch(arr, left, mid - 1, findVal);  
69.             } else if (findVal > arr[mid]) { //  说明应该向右边递归  
70.                 return insertVauleSearch(arr, mid + 1, right, findVal);  
71.             } else {  
72.                 return mid;  
73.             }  
74.         }  
75.     }  
76. }  

 

posted @ 2020-11-02 16:53  白刃天使  阅读(222)  评论(0编辑  收藏  举报