一、线性查找
源码:线性查找
1,思路
线性查找又称顺序查找,是一种最简单的查找方法,它的基本思想是从第一个记录开始,逐个比较记录的关键字,直到和给定的K值相等,则查找成功;若比较结果与文件中n个记录的关键字都不等,则查找失败。
2,特点
- 按顺序查找,数组(集合)可以无序
- 时间复杂度:O(N)
3,代码实现
/** * 线性查找找到一个满足条件的值就返回 */ public static int seqSearch(int[] arr, int value) { // 线性查找是逐一比对,发现有相同值,就返回下标 for (int i = 0; i < arr.length; i++) { if (arr[i] == value) { return i; } } return -1; }
二、二分查找(折半)
源码:二分查找
1,思路
1)定义两个辅助指针:left、right ,待查找的元素在 arr[left]~arr[right] 之间 2)eft 初始值为 0 ,right 初始值为 arr.length - 1 3)将数组分成两半:int mid = (left + right) / 2; ,取数组中间值与目标值 findVal 比较 如果 mid > val,说明待查找的值在数组左半部分,令right = mid-1 递归查 如果 mid < val ,说明待查找的值在数组右半部分,令left = mid+1递归查 如果 mid == val,查找到目标值,返回mid即可 4)未找到目标值:left > right ,直接返回-1
2,特点
- 数组(集合)必须有序
- 时间复杂度:O(log2N)
3,代码实现
/** * 二分查找算法 */ public static int binarySearch(int[] arr, int left, int right, int val) { if (left > right) { return -1; } int mid = (left + right) / 2; if (val > arr[mid]) { return binarySearch(arr, mid + 1, right, val); } else if (val < arr[mid]) { return binarySearch(arr, left, mid - 1, val); } else { return mid; } }
三、插值查找
源码:插值查找
1,介绍
- 插值查找算法类似于二分查找, 不同的是插值查找每次从自适应 mid 处开始查找。
- 求mid的公式为:int mid = low + (high - low) * (key - arr[low]) / (arr[high] - arr[low])
2,思路
基本与二分查找相同,不同之处为: 1,求mid的公式不同:int mid = left + (right – left) * (findVal – arr[left]) / (arr[right] – arr[left]) 2,判断未找到目标:left>right || val< arr[left] || val> arr[right]
3,特点
- 数组(集合)必须有序
- 对于数据量较大,关键字分布比较均匀(最好是线性分布)的查找表来说,采用插值查找,速度较快
- 时间复杂度:O(log2(log2N))
4,代码实现
public static int insertValSearch(int[] arr,int left , int right,int val) { System.out.println("插值查找~~"); if (left > right || arr[left] > val || arr[right] < val) { return -1; } int mid = left + (right - left) * (val - arr[left]) / (arr[right] - arr[left]); if (val > arr[mid]) { return insertValSearch(arr, mid + 1, right, val); } else if (val < arr[mid]) { return insertValSearch(arr, left, mid - 1, val); }else { return mid; } }
四、斐波拉契查找算法
源码:斐波拉契查找算法
1,思路
参考:斐波拉契查找简介
2,特点
- 如果要查找的记录在右分区,则左分区的数据都不用再判断了,不断反复进行下去,对处于当中的大部分数据,其工作效率要高一些。所以,尽管斐波那契查找的时间复杂度也为
O(logn)
,但就平均性能来说,斐波那契查找要优于折半查找。可惜如果是最坏的情况,比如这里的key=1,那么始终都处于左分区在查找,则查找效率要低于折半查找。左分区要比右分区大嘛。 - 时间复杂度:O(log2N)
3,代码
/** * 查找 */ public static int fibonacciSearch(int[] arr, int val) { int left = 0; int right = arr.length - 1; int[] f = fib(); int k = 0; while (right > f[k] - 1) { k++; } //拷贝临时数组 比原始数组长的部分会直接用0补齐 int[] temp = Arrays.copyOf(arr, f[k]); //将长于arr部分用高位值补齐 for (int i = right + 1; i < temp.length; i++) { temp[i] = arr[right]; } int mid = 0; while (left <= right) { mid = left + f[k - 1] - 1; if (val < temp[mid]) { //向左找 right = mid - 1; k--; } else if (val > temp[mid]) { //向右找 left = mid + 1; k -= 2; } else { if (mid < right) { return mid; } else { //如果查到的是扩容之后的数值,就直接返right return right; } } } return -1; }