查找主要包含三种:
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;
}