概述
在Java中,常用的查找算法有四种:顺序(线性)查找、二分查找/折半查找、插值查找、裴波那契查找
线性查找算法
原理
按着数组的顺序逐一比对,如果相等就返回下标,不相等又进行下一个元素的比较,直到数组中元素对比完。
代码实现
1
2
3
4
5
6
7
8
9private static int seqSearch(int[] arr, int value) { for (int i = 0; i < arr.length; i++) { if (arr[i] == value) { return i; } } return -1; }
二分查找算法
原理
1.首先确定该数组的中间下标mid=[left+right]/2
2.然后让需要查找的数findVal和arr[mid]比较
2.1 findVal>arr[mid],说明要查找的数在mid的右边,因此需要递归向右查找
2.2 findVal<arr[mid],说明要查找的数再mid的左边,因此需要递归向左查找
2.3 findVal==arr[mid],说明找到要查找的数,直接返回下标
3.什么时候需要结束递归?
1)找到就结束
2)递归完整个数组,仍然没有找到findVal,也需要结束递归,即left>right
注意:使用二分查找时,数组是有序的
代码实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16private 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; } }
插值查找算法
原理
插值查找算法类似于二分查找,不同的是插值查找每次从自适应mid处开始查找。将折半查找中的求mid索引的公式,low表示左边索引left,high表示右边索引right,key为findVal
mid=(low+high)/2=low+1/2(high-low)改成mid=low+(key-a[low])/(a[high]-a[low])(high-low)
代码实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15private static int insertValueSearch(int[] arr, int left, int right, int findVal) { if (left > right || findVal < arr[0] || findVal > arr[arr.length - 1]) { return -1; } int mid = left + (right - left) * (findVal - arr[left]) / (arr[right] - arr [left]); int midVal = arr[mid]; if (findVal > midVal) { return insertValueSearch(arr, mid + 1, right, findVal); } else if (findVal < midVal) { return insertValueSearch(arr, left, mid - 1, findVal); } else { return mid; } }
注意事项:
1.对于数据量较大,关键字分布比较均匀的查找表来说,采用插值查找, 速度较快
2.关键字分布不均匀的情况下,该方法不一定比折半查找要好
裴波那契(黄金分割法)查找算法
原理
黄金分割点是指把一条线段分割为两部分,使其中一部分与全长之比等于另一部分与这部分之比。取其前三位数字的近似值是0.618。由于按此比例设计的造型十分美丽,因此称为黄金分割,也称为中外比。这是一个神奇的数字,会带来意向不大的效果。
斐波那契数列 {1, 1, 2, 3, 5, 8, 13, 21, 34, 55 } 发现斐波那契数列的两个相邻数 的比例,无限接近 黄金分割值0.618。
斐波那契查找原理与前两种相似,仅仅改变了中间结点(mid)的位置,mid不再是中间或插值得到,而是位于黄金分割点附近,即mid=low+F(k-1)-1(F代表斐波那契数列),如下图所示
对F(k-1)-1的理解:
1.由斐波那契数列 F[k]=F[k-1]+F[k-2] 的性质,可以得到 (F[k]-1)=(F[k-1]-1)+(F[k-2]-1)+1 。该式说明:只要顺序表的长度为F[k]-1,则可以将该表分成长度为F[k-1]-1和F[k-2]-1的两段,即如上图所示。从而中间位置为mid=low+F(k-1)-1
2.类似的,每一子段也可以用相同的方式分割
3.但顺序表长度n不一定刚好等于F[k]-1,所以需要将原来的顺序表长度n增加至F[k]-1。这里的k值只要能使得F[k]-1恰好大于或等于n即可,由以下代码得到,顺序表长度增加后,新增的位置(从n+1到F[k]-1位置),都赋为n位置的值即可
1
2
3
4while (n > fib(k) - 1) { k++; }
代码实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41public static int fibSearch(int[] a, int key) { int low = 0; int high = a.length - 1; int k = 0;//表示斐波那契分割数值的下标 int mid = 0; int f[] = fib(); while (high > f[k] - 1) { k++; } int[] temp = Arrays.copyOf(a, f[k]); for (int i = high + 1; i < temp.length; i++) { temp[i] = a[high]; } while (low <= high) { mid = low + f[k - 1] - 1; if (key < temp[mid]) { high = mid - 1; k--; } else if (key > temp[mid]) { low = mid + 1; k -= 2; } else { if (mid <= high) { return mid; } else { return high; } } } return -1; } public static int[] fib() { int[] f = new int[maxSize]; f[0] = 1; f[1] = 1; for (int i = 2; i < maxSize; i++) { f[i] = f[i - 1] + f[i - 2]; } return f; }
最后
以上就是痴情母鸡最近收集整理的关于数据结构与算法之四种查找算法概述线性查找算法二分查找算法插值查找算法裴波那契(黄金分割法)查找算法的全部内容,更多相关数据结构与算法之四种查找算法概述线性查找算法二分查找算法插值查找算法裴波那契(黄金分割法)查找算法内容请搜索靠谱客的其他文章。
发表评论 取消回复