在Java中,常用的查找算法有四种 1)顺序(线性)查找 2)二分查找 3)插值查找 4)斐波那契查找
这个就不用多说了,直接循环遍历就行
public static int Search(int[] arr,int value){ for(int i=0;i<arr.length;i++){ if(arr[i]==value){ return i; } } return -1; }原理: 二分查找只能查找有序数列 类似于归并排序中 “分” 的思想,指定待查找的数组的前后索引,找到数组中值 mid=(left+right)/ 2 ,若待查找值等于 arr [mid] ,返回索引 mid,若小于arr [mid] ,向左递归,若大于,向右递归。
注意事项: 1)二分查找只能查找有序数组 2)当left>right时,说明查找的数不存在,返回-1,中止递归 3)对于待查找的数在数组中出现多次,需要在递归出口向已知索引两边搜 索,找到相同的值的索引存储在容器中并返回
代码:
/** * * @param arr 原数组 * @param left 左索引 * @param right 由索引 * @param value 待查找值 * @return 返回存储带索引值的容器 */ public static List<Integer> binarySearch(int[] arr,int left,int right,int value){ //若left>right,没有找到该值,返回空容器 if(left>right){ return new ArrayList<Integer>(); } int mid=(left+right)/2; int count=arr[mid]; //小于中值,向左递归 if(value<count){ return binarySearch(arr,left,mid,value); } //大于中值,向右递归 else if(value>count){ return binarySearch(arr,mid+1,right,value); } //等于中值,需要向两边搜索 //将找到的索引存入容器List中 else{ List<Integer> list=new ArrayList<Integer>(); int index=mid-1; //向已找到的索引值左边搜索 while(index>=0&&arr[index]==value){ list.add(index); index--; } list.add(mid); index=mid+1; //向右边搜索 while(index<=arr.length-1&&arr[index]==value){ list.add(index); index++; } return list; } }原理: 插值查找和二分查找类似,唯一的区别就是中值的确定,这里应用公式 mid=left+(right-left)*(value-arr[left])/(arr[right]-arr[left]),对于分布均匀的数组,他可以快速找到待查找的位置,例如:0-100以1递增的有序数组,查找1插值查找只需要递归一次,而二分查找需递归五次。
二分与插值查找的区别: 1)对于分布较均匀的数组,用插值查找较快 2)对于变化较大的数组,适用于二分查找
注: 二分查找不能查找数字全部相同的数组
代码:
public static List<Integer> insertSearch(int[] arr,int left,int right,int value){ System.out.println("scsa"); //若left>right,没有找到该值,返回空容器 //当value<arr[0]||value>arr[arr.length-1]时,mid的值会越界 if(left>right||value<arr[0]||value>arr[arr.length-1]){ return new ArrayList<Integer>(); } int mid=left+(right-left)*(value-arr[left])/(arr[right]-arr[left]); int count=arr[mid]; //小于中值,向左递归 if(value<count){ return insertSearch(arr,left,mid,value); } //大于中值,向右递归 else if(value>count){ return insertSearch(arr,mid+1,right,value); } //等于中值,需要向两边搜索 //将找到的索引存入容器List中 else{ List<Integer> list=new ArrayList<Integer>(); int index=mid-1; //向已找到的索引值左边搜索 while(index>=0&&arr[index]==value){ list.add(index); index--; } list.add(mid); index=mid+1; //向右边搜索 while(index<=arr.length-1&&arr[index]==value){ list.add(index); index++; } return list; } }原理: 斐波那契查找原理与前两种相似,仅仅改变了中间节点mid的位置,mid位于数组的黄金分割点附近,即mid=low+F[ k-1 ] - 1,如图: 除此之外,F[k-1]-1一定要大于原数组的长度n,否则,将原数组用 arr [ n - 1 ] 扩充为长度为F[k-1]-1的数组
代码:
/** * 斐波那契数列 * * @return */ public static int[] fibonacci() { int[] f = new int[20]; int i = 0; f[0] = 1; f[1] = 1; for (i = 2; i < MAXSIZE; i++) { f[i] = f[i - 1] + f[i - 2]; } return f; } public static int fibonacciSearch(int[] data, int key) { int low = 0; int high = data.length - 1; int mid = 0; // 斐波那契分割数值下标 int k = 0; // 序列元素个数 int i = 0; // 获取斐波那契数列 int[] f = fibonacci(); // 获取斐波那契分割数值下标 while (data.length > f[k] - 1) { k++; } // 创建临时数组 int[] temp = new int[f[k] - 1]; for (int j = 0; j < data.lengt敏感词emp[j] = data[j]; } // 序列补充至f[k]个元素 // 补充的元素值为最后一个元素的值 for (i = data.length; i < f[k] - 1; i++) { temp[i] = temp[high]; } for (int j : temp) { System.out.print(j + " "); } System.out.println(); while (low <= high) { // low:起始位置 // 前半部分有f[k-1]个元素,由于下标从0开始 // 则-1 获取 黄金分割位置元素的下标 mid = low + f[k - 1] - 1; if (temp[mid] > key) { // 查找前半部分,高位指针移动 high = mid - 1; // (全部元素) = (前半部分)+(后半部分) // f[k] = f[k-1] + f[k-1] // 因为前半部分有f[k-1]个元素,所以 k = k-1 k = k - 1; } else if (temp[mid] < key) { // 查找后半部分,高位指针移动 low = mid + 1; // (全部元素) = (前半部分)+(后半部分) // f[k] = f[k-1] + f[k-1] // 因为后半部分有f[k-1]个元素,所以 k = k-2 k = k - 2; } else { // 如果为真则找到相应的位置 if (mid <= high) { return mid; } else { // 出现这种情况是查找到补充的元素 // 而补充的元素与high位置的元素一样 return high; } } } return -1; }