查找算法-志宇

二分法

思想
每次和中间值进行比较(以中间点为分割点)
如果中间值小则取中间值右侧部分中间值继续比较
如果中间值大则取中间值左侧部分中间值继续比较
代码

public class BinarySearchFind {
    public static void main(String[] args) {
    	int [] arr = {1,8, 10, 89, 1000, 1234};
    	int binarySearch = binarySearch(arr,0,arr.length-1,1234);
    	System.out.println(arr[binarySearch]);
	}

	private static int binarySearch(int[] arr, int left, int right,int searchValue) {
		//代表数组中没有这个值
		if(left>right){
			return -1;
		}
		//取得中间值
		int mid=(left+right)/2;
		if(searchValue<arr[mid]){
			//向左面进行查找
			return binarySearch(arr,left,mid-1,searchValue);
		}else if(searchValue>arr[mid]){
			//向右面进行查找
			return binarySearch(arr,mid+1,right,searchValue);
		}else{
			//返回位置
			return mid;
		}
	}
}

插值查找算法

思想
和二分查找思想相同,
只是每次取的不是中间点(根据比例计算获得分割点)
如下图:中间切割点如下
在这里插入图片描述
如下图:经过中间切割点思想 可以按比例获得切割点位置
在这里插入图片描述
优点:对于数据量较大,关键字分布比较均匀的查找,采用插值查找, 速度比二分法快.
代码

public class BinarySearchFind {
    public static void main(String[] args) {
    	int [] arr = {1,8, 10, 89, 1000, 1234};
    	int binarySearch = binarySearch(arr,0,arr.length-1,1234);
    	System.out.println(arr[binarySearch]);
	}

	private static int binarySearch(int[] arr, int left, int right,int searchValue) {
		//代表数组中没有这个值
		if(left>right){
			return -1;
		}
		//取得中间值
		int mid=left+(searchValue-arr[left])/(arr[right]-arr[left])*(right-left);
		if(searchValue<arr[mid]){
			//向左面进行查找
			return binarySearch(arr,left,mid-1,searchValue);
		}else if(searchValue>arr[mid]){
			//向右面进行查找
			return binarySearch(arr,mid+1,right,searchValue);
		}else{
			//返回位置
			return mid;
		}
	}
}

斐波那契(黄金分割法)查找算法

思想
每次以0.618为分割点,在众多数据中的得到的数据更加完美,但速度较慢
代码

public class BinarySearchFind {
    public static void main(String[] args) {
        int [] arr = {1,8, 10, 89, 1000, 1234};
		System.out.println("index=" + fibSearch(arr, 1234));
	}
    private static int fibSearch(int[] arr, int searchValue) {
    	//创建对应的斐波那契数组
        int []  feiBoArr=new int[30];
        CreateFibonacciArray(feiBoArr);
        //找到数组长度对应的斐波那契数中的值
        int k=0;
    	while(feiBoArr[k]<arr.length){
    		k++;
    	}
    	//将数组填充斐波那契长度,多出长度用0填充
    	int[] tempArr=Arrays.copyOf(arr, feiBoArr[k]);
    	
    	//将最大数填充到数组末尾   [1, 8, 10, 89, 1000, 1234, 1234, 1234]
    	for(int i=arr.length;i<tempArr.length;i++){
    		tempArr[i]=arr[arr.length-1];
    	}
    	
    	int left=0;
    	int right=tempArr.length-1;
    	
    	while(left<right){
    		//中间坐标位置 =左面坐标+斐波纳契中间坐标
    		int mid=left+feiBoArr[k-1];
	    	if(searchValue >tempArr[mid]){//要查找的值在右面
	    		  left=mid+1;
	    		  //1. 全部元素 = 前面的元素 + 后边元素
	    		  //2. f[x]=f[x-2]+f[x-1]
	    		  //其中f[x-2] 为左面部分,f[x-1]为右面部分
	    		  //f[x-2]<f[x-1], 右面部分大
	    		  //下次的分割点就是  f[x-1-1]
	    		  k--;
	    	}else if(searchValue < tempArr[mid]){//要查找的值在左面
	    		  right=mid-1;
	    		  //1. 全部元素 = 前面的元素 + 后边元素
	    		  //2. f[x]=f[x-2]+f[x-1]
	    		  //其中f[x-2] 为左面部分,f[x-1]为右面部分
	    		  //f[x-2]<f[x-1], 左面部分小  
	    		  //下次的分割点就是  f[x-2-1]
	              k--;
	    		  k--;
	    	}else{
	    		//因为后面有的数是填充的,如果匹配到填充的数,则直接返回数组最大索引
	    		if(arr[arr.length-1]==tempArr[mid])
	    		{
                   return arr.length-1;
	    		}
	    		return mid;
	    	}
    	}
		return -1;
	}
    /**
     * 创建斐波那契数组
     */
	public static void CreateFibonacciArray(int[] arr){
    	arr[0]=1;
    	arr[1]=1;
    	for(int i=2;i<arr.length;i++){
    	    arr[i]=arr[i-1]+arr[i-2];	
    	}
    }
	
}

字符串暴力匹配算法

思想
每次只移动一位,若是不匹配,移动到下一位接着判断,浪费了大量的时间
代码

public class ViolenceMatch {
      public static void main(String[] args) {
		String str="asdfa asdfb asdfc asdfd";
    	String match="asdfc";
    	int index=violenceMatch(str,match);
    	System.out.println(index);
	  }

	private static int violenceMatch(String str, String match) {
		//每次匹配失败复原的位置
        int temp=0;
        //循环遍历每个字符
		for(int i=0,j=0;i<str.length();i++){
			temp=i;
			while(str.charAt(i) == match.charAt(j)){
				i++;
				j++;
				if(j == match.length()){
					//返回匹配出来的位置
					return i-match.length();
				}
			}
			//这里应用回溯
			i=temp;
			j=0;
		}
		return -1;
	}
}

kmp字符串匹配算法

思想
在匹配不成功时回溯的位置不是下一位,而是经过计算的指定位置
图解
部分匹配值”就是”前缀”和”后缀”的最长的共有元素的长度。以”ABCDABD”为例
-”A”的前缀和后缀都为空集,共有元素的长度为0;
-”AB”的前缀为[A],后缀为[B],共有元素的长度为0;
-”ABC”的前缀为[A, AB],后缀为[BC, C],共有元素的长度0;
-”ABCD”的前缀为[A, AB, ABC],后缀为[BCD, CD, D],共有元素的长度为0;
-”ABCDA”的前缀为[A, AB, ABC, ABCD],后缀为[BCDA, CDA, DA, A],共有元素为”A”,A的长度为1;
-”ABCDAB”的前缀为[A, AB, ABC, ABCD, ABCDA],后缀为[BCDAB, CDAB, DAB, AB, B],共有元素为”AB”,AB的长度为2;
-”ABCDABD”的前缀为[A, AB, ABC, ABCD, ABCDA, ABCDAB],后缀为[BCDABD, CDABD, DABD, ABD, BD, D],共有元素的长度为0。
在插入图片描述
代码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值