查找方法总结(Java)

1、线性查找

基本概念:

线性查找又称顺序查找,是一种最简单的查找方法,它的基本思想是从第一个记录开始,逐个比较记录的关键字,直到和给定的K值相等,则查找成功;若比较结果与文件中n个记录的关键字都不等,则查找失败。

代码实现:

public class SeqSearch {

	public static void main(String[] args) {
		int[] arr = {11,2,5,1,3,8,6};
		int index = seqSearch(arr, 1);
		if(index == -1) {
			System.out.println("数组中不含1!");
		}
		else {
			System.out.println("1在数组中的下标为"+index);
		}
	}
	public static int seqSearch(int[] array,int value) {
		for(int i =0 ;i<array.length;i++) {
			if(array[i] == value)
				return i;
		}
		return -1;
	}
}

二分查找法

1、概念:

二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列。

2、思路分析:

1、首先确定该数组的中间下标,mid=(left+right)/2
2、然后让需要查找的数value与arr[mid]进行比较:
如果arr[mid]>value,则进行左递归BinSearch(arr, left, mid-1, findValue);
如果arr[mid]<value,则进行右递归BinSearch(arr, mid+1, right, findValue);
如果arr[mid]==value,return mid;
//什么时候要结束递归:
1、已找到arr[mid]==value,就return;
2、如果left>right,结束递归,return -1;

3、详细代码:

第一种(不考虑数组中有要查找的重复元素)
public class BinarySearch {

	public static void main(String[] args) {
		int[] arr = {1,2,3,4,5,6,7,8,9};
		int index = BinSearch(arr, 0, arr.length-1,10);
		System.out.println("index = "+index);

	}
	public static int BinSearch(int[] arr,int left,int right,int findValue) {
		if(left>right) {
			return -1;
		}
		int mid = (left+right)/2;
		int midValue = arr[mid];
		if(findValue>midValue) {
			return BinSearch(arr, mid+1, right, findValue);
		}
		else if(findValue<midValue) {
			return BinSearch(arr, left, mid-1, findValue);
		}
		else {
			return mid;
		}
	}
}
第二种(不考虑数组中有要查找的重复元素)
思路分析:

1、找到mid索引值之后不要return
2、向mid索引值左边进行扫描,若存在arr[temp] = findValue,将temp加入list并temp–;
3、将mid加入list
4、向mid索引值右边进行扫描,若存在arr[temp] = findValue,将temp加入list并temp++;

import java.util.ArrayList;

public class BinarySearch {

	public static void main(String[] args) {
		int[] arr = {1,1,2,3,4,5,6,7,7,8,9};
		ArrayList<Integer> index = BinSearch(arr, 0, arr.length-1,1);
		System.out.println("index = "+index);

	}
	public static ArrayList<Integer> BinSearch(int[] arr,int left,int right,int findValue) {
		if(left>right) {
			return new ArrayList<Integer>();
		}
		int mid = (left+right)/2;
		int midValue = arr[mid];
		if(findValue>midValue) {
			return BinSearch(arr, mid+1, right, findValue);
		}
		else if(findValue<midValue) {
			return BinSearch(arr, left, mid-1, findValue);
		}
		else {
			int temp = mid-1;
			ArrayList<Integer> list = new ArrayList<Integer>();
			while(true) {
				if(temp<0||arr[temp]!=findValue) {
					break;
				}
				list.add(temp);
				temp-=1;
			}
			list.add(mid);
			temp = mid+1;
			while(true) {
				if(arr[temp]!=findValue||temp>arr.length-1) {
					break;
				}
				list.add(temp);
				temp+=1;
			}
			return list;
		}
		}
}
输出:
index = [0, 1]

插值查找

1、算法思想:

1、插值查找类似于二分查找,不同的是,插值查找每次从自适应mid处开始查找
2、将二分查找中mid的所以公式变为:mid = left+(right-left)*(findValue-arr[left])/(arr[right]-arr[left]);

2、详细代码:

public class InscertValueSearch {

	public static void main(String[] args) {
		int[] arr = new int[100];
		for(int i = 0;i<100;i++) {
			arr[i] = i+1;
		}
		int index = inserctValueSearch(arr, 0, arr.length-1, 52);
		System.out.println("index = "+index);
	}
	
	public static int inserctValueSearch(int[] arr,int left,int right,int findValue) {
		if(left>right||findValue>arr[arr.length-1]||findValue<arr[0]) {
			return -1;
		}
		int mid = left+(right-left)*(findValue-arr[left])/(arr[right]-arr[left]);
		if(findValue>arr[mid]) {
			return inserctValueSearch(arr, mid+1, right, findValue);
		}
		if(findValue<arr[mid]) {
			return inserctValueSearch(arr, left, mid-1, findValue);
		}
		else {
			return mid;
		}
	}
}

3、注意事项:

1、对于数据量比较大,关键值分布比较均匀的查找表来说,采用插值查找速度较快。
2、关键值分布不均匀的情况下,采用插值查找不一定比二分查找好

斐波那契查找

1、算法原理:

斐波那契查找原理与前两种相似,仅仅改变了中间结点(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位置的值即可。

2、详细代码:

import java.util.Arrays;

public class FiboSearch {
	public static int MaxSize = 20;
	public static void main(String[] args) {
		int[] arr = {1,8,10,89,1000,1234};
		int index = fibSearch(arr, 8);
		System.out.println("index = "+index);
	}
	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;
	}
	public 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++;
		}
		//因为f[k]大于数组的长度,因此需要使用一个array类构造一个新的数组并指向a
		//不足的部分会使用零填充
		int[] temp=Arrays.copyOf(a, f[k]);
		//对新的数组temp中的零用a[high]填充
		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;
				//再次循环时mid = f[k-1-1]-1
				k--;
			}
			else if(key>temp[mid]) {
				low = mid +1;
				//再次循环时mid = f[k-2-1]-1
				 k=k-2;
			}
			else {
				if(mid<high)
					return mid;
				else
					return high;
			}
		}
		return -1;
	}
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值