zoukankan      html  css  js  c++  java
  • 【Java】二分查找、插值查找、斐波那契查找的实现,及分析


    public class Search {
    	
    	/**1.顺序查找		时间复杂度为:O(n)
    	*/
    	public static int SequenceSearch(int[] a, int x) {
    		for(int i=0;i<a.length;i++) {
    			if(x==a[i])
    				return i;
    		}
    		return -1;
    	}
    	
    	
    	/**2.二分查找,数组已有序  时间复杂度为: O(log(n))
    		在有序数组中,设置下标left和right,每次从中间mid处找,若所需找的的x小于a[mid],则令right为mid-1,继续从该区域找;
    		若所需找的的x大于a[mid],令left=mid+1,重复,直至left>right(注意,left和right相等也要考虑进去);
    	*/
    	public static int BinarySearchNoR(int[] a, int x){
    		int left=0, right=a.length-1;
    		
    		while(left<=right){
    			int mid = left+((right-left)>>1);
    			if(a[mid]>x){
    				right = mid-1;
    			}
    			else if(a[mid]<x){
    				left = mid+1;
    			}
    			else{
    				return mid;
    			}
    		}
    		return -1;
    	}
    	
    	//递归版
    	public static int BinarySearchR(int[] a, int x, int left, int right){
    		int mid = left+((right-left)>>1);
    		
    		if(left>right){
    			return -1;
    		}
    		
    		if(x<a[mid]){
    			return BinarySearchR(a,x,left,mid-1);
    		}
    		else if(x>a[mid]){
    			return BinarySearchR(a,x,mid+1,right);
    		}
    		else{
    			return mid;
    		}
    		
    		
    	}
    		
    	
    		
    	/**3.插值查找
    		插值查找算法类似于二分查找,不同的是插值查找每次从自适应mid处开始查找,例如我们要从1~100找5这个数,
    		那我们就会从前边开始找,插值查找就是应用这种原理
    		插值公式: mid = left+(x-a[left])/(a[right]-a[left])*(right-left);
    	*/
    	public static int InsertValueSearchR(int[] a, int x , int left, int right){
    		
    		if(x<a[0]||x>a[a.length-1]){	//不加这句会抛出异常,若找的数不在范围内,则mid可能越界
    			return -1;
    		}
    		int mid = left + (x-a[left])/(a[right]-a[left])*(right-left);
    		if(left>right){
    			return -1;
    		}
    		if(x<a[mid]){
    			return InsertValueSearchR(a,x,left,mid-1);
    		}
    		else if(x>a[mid]){
    			return InsertValueSearchR(a,x,mid+1,right);
    		}
    		else{
    			return mid;
    		}
    	}
    	
    	/**Fibonacci查找(下面附图)
    		基于二分查找的提升,也是有序查找,每次将数组分为两部分,不同的是使用斐波那契数的前两项和等于后一项的原理来实现;
    		斐波那契数:0,1,1,2,3,5,8,13,21,34,55,89...
    		创建一个临时数组,将目标数组拷贝该临时数组中,并使他的长度为斐波那契里的元素-1;且最后的元素都为right的值;
    		if x<a[mid]
    			right=mid-1;  区域划分到左
    			k-=1;   左部分数组个数
    		else if x>a[mid]
    			left=mid+1;   区域划分到右
    			k-=2;   右部分数组个数
    		else   x==a[mid]
    			if x<a.lenght
    				return mid;
    			else	在扩展的数组中找到,返回a的最后一个下标
    				return right;
    	*/
    	//创建斐波那契数组
    	public static void fibonacci(int[] f){
    		f[0]=0;
    		f[1]=1;
    		for(int i=2;i<f.length;++i){
    			f[i]=f[i-1]+f[i-2];
    		}
    		
    	}
    	
    	public static int FibonacInsearch(int[] a, int x){
    		int left=0, right=a.length-1;
    		int k=0;
    		int FIB_MAX = 20;
    		int[] f = new int[FIB_MAX];
    		fibonacci(f);
    		
    		while(a.length>f[k]-1){
    			k++;
    		}
    		
    		int[] tmp = new int[f[k]-1];
    		System.arraycopy(a,0,tmp,0,a.length);//拷贝a元素到tmp中
    		for(int i=a.length;i<f[k]-1;++i){	//right以后的值都相同
    			tmp[i]=a[right];
    		}
    		
    		while(left<=right){
    			int mid = left+f[k-1]-1;
    			if(x<a[mid]){
    				right=mid-1;
    				k-=1;
    			}
    			else if(x>a[mid]){
    				left=mid+1;
    				k-=2;
    			}
    			else{
    				if(mid<a.length)
    					return mid;
    				else		//扩展里找到x,返回a的最后一个下标
    					return a.length-1;
    
    			}
    		}
    		return -1;
    		
    	}
    
    
           public static void main(String[] args) {
    		int[] a = {5,1,3,8,9,6,4,7,8,5,2};
    		System.out.println(SequenceSearch(a,9));
    		System.out.println();
    		int[] seq = {1,2,3,4,5,7,8,9};
    		System.out.println("二分");
    		System.out.println(BinarySearchNoR(seq,1));
    		System.out.println(BinarySearchNoR(seq,6));
    		System.out.println(BinarySearchNoR(seq,9));
    		System.out.println("二分递归");
    		System.out.println(BinarySearchR(seq,1,0,seq.length-1));
    		System.out.println(BinarySearchR(seq,5,0,seq.length-1));
    		System.out.println(BinarySearchR(seq,8,0,seq.length-1));
    		System.out.println(BinarySearchR(seq,9,0,seq.length-1));
    		System.out.println("插值查找");
    		System.out.println(InsertValueSearchR(seq,0,0,seq.length-1));
    		System.out.println(InsertValueSearchR(seq,1,0,seq.length-1));
    		System.out.println(InsertValueSearchR(seq,8,0,seq.length-1));
    		System.out.println(InsertValueSearchR(seq,6,0,seq.length-1));
    		System.out.println("斐波那契查找");
    		System.out.println(FibonacInsearch(seq,1));
    		System.out.println(FibonacInsearch(seq,0));
    		System.out.println(FibonacInsearch(seq,9));
    		System.out.println(FibonacInsearch(seq,23));
    	}
    }

    斐波那契:



  • 相关阅读:
    关于素数的具体问题
    Scala Apply
    Scala内部类
    Scala 类和对象
    Scala Tuple类型
    Scala数组
    sql server 游标
    表变量和临时表详解
    子查询详解
    EXEC 和 SP_EXECUTESQL的区别
  • 原文地址:https://www.cnblogs.com/yongtaochang/p/13615359.html
Copyright © 2011-2022 走看看