查找

查找主要包含三种:

1.顺序查找

2.折半查找

3.裴波那契查找


顺序查找是从头到尾遍历一般,时间复杂度为O(n)

折半查找就是二分法查找,把数组绘制成一棵二叉树,时间复杂度为O(logn),要比顺序查找高效。

裴波那契利用了黄金分割原理来实现时间复杂度也是O(logn),但从平均性能说要优于折半查找,最坏的情况下比折半查找要差。


注意这里的数据已经是在有序情况下的了。


折半查找实现:主要是获取到折半的下标。

public  static int  BinarySearch(int[] datas,int searchtarget)
{
    int length=datas.length;
    int hight=length-1;
    int low=0;
    int mid=hight/2;
    while(low<=hight)
    {
        if(datas[mid]==searchtarget)
            return datas[mid];
        else if(searchtarget<datas[mid]){

            hight=mid-1;
            length=mid-low;
        }
        else if(searchtarget>datas[mid]) {
            low=mid+1;
            length=hight-low;

        }
        mid=length/2+low;
    }
    return -1;
}


裴波那契查找实现:

裴波那契定义:斐波那契数列,又称黄金分割数列,指的是这样一个数列:0、1、1、2、3、5、8、13、21、34、……在数学上,斐波纳契数列以如下被以递归的方法定义:F(0)=0,F(1)=1,F(n)=F(n-1)+F(n-2)(n≥2,n∈N*)

裴波那契查找算法核心:

1)当key=a[mid]时,查找成功;
2)当key<a[mid]时,新的查找范围是第low个到第mid-1个,此时范围个数为F[k-1] - 1个,即数组左边的长度,所以要在[low, F[k - 1] - 1]范围内查找;
3)当key>a[mid]时,新的查找范围是第mid+1个到第high个,此时范围个数为F[k-2] - 1个,即数组右边的长度,所以要在[F[k - 2] - 1]范围内查找

注意点:

如果一个有序表的元素个数为n,并且n正好是(某个斐波那契数 - 1),即n=F[k]-1时,才能用斐波那契查找法。 如果有序表的元素个n不等于(某个斐波那契数 - 1),即n≠F[k]-1,这时必须要将有序表的元素扩展到大于n的那个斐波那契数 - 1才行

对于二分查找,分割是从mid= (low+high)/2开始;而对于斐波那契查找,分割是从mid = low + F[k-1] - 1开始的; 通过上面知道了,数组a现在的元素个数为F[k]-1个,即数组长为F[k]-1,mid把数组分成了左右两部分, 左边的长度为:F[k-1] - 1, 那么右边的长度就为(数组长-左边的长度-1), 即:(F[k]-1) - (F[k-1] - 1) = F[k] - F[k-1] - 1 = F[k-2] - 1。

算法实现代码:

  /** 获取裴波那契数列
     * @param length 数列长度
     * @return 数列数组
     */
public static int[] getP(int length)
{
    int[] p=new int[length];
  for(int i=0;i<length;i++)
  {
      p[i]=getp(i);
  }
    return p;
}

    /**获取裴波那契数
     * @param index
     * @return
     */
 public static int getp(int index)
 {
     if(index==0)
         return  0;
     if(index==1)
         return 1;
     return getp(index-1)+getp(index-2);
 }


    /**裴波那契查找
     * @param datas
     * @param target
     * @return
     */
 public static int SearchP(int[] datas,int target)
 {   int low=0;
     int heigh=datas.length-1;
     int[] p=getP(datas.length);
     int k=getK(p, datas.length);//找到k值
     int mid=low+p[k-1]-1;
     while(low<=heigh)
     {
         if(datas[mid]==target)
             return mid;
         else if(target<datas[mid])
         {   heigh=mid-1;
             mid=low+p[k-1]-1;
             k=k-1;
         }
         else if(target>datas[mid])
             {
                 low=mid+1;
                 mid=low+p[k-2]-1;
                 k=k-2;
             }

     }

     return -1;
 }

public static int getK(int[] P,int n)
{
    int K=0;
    while (P[K]-1<n) {
     K++;
    }
    return K;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值