首先看折半查找,字面意思就能看出来是什么意思。定义三个“哨兵”,low,mid,high。其中mid=low+high/2,然后比较位置mid的元素与待查找元素的大小。如果key大于mid位置所对应的元素,则要查找的元素在数组的下半部分,重新为low赋值,low=mid+1;如果key小于mid位置对应的元素,则需要查找数组的上半部分,则high=mid-1。按照这样的规则在数组中遍历,找到待查找的元素后终止。
下面看代码实现:
int binary_find(int arr[],int key,int n)
{
int high,mid,low;
high=n-1;
low=0;
while(low<=high)
{
mid=(low+high)/2;
if(key<arr[mid])
high=mid-1;
else if(key>arr[mid])
low=mid+1;
else if(key==arr[mid])
return mid;
else
return -1;
}
}
下面查看另一个查找方法,插值查找,与折半查找类似,也有三个“哨兵”,不过这次mid的取值不是通过简单low与high相加的一般。mid的取值是要通过计算key与low所对应元素的差异性。mid=low + ( key - a[low] ) * ( high - low ) / ( a[high]-a[low] )。后面的查找过程与折半查找类似。
int insertvalue_find(int arr[],int key,int n)
{
int high,mid,low;
high=n-1;
low=0;
while(low<=high)
{
mid=low+(high-low)*(key-arr[low])/(arr[high]-arr[low]);
if(key<arr[mid])
high=mid-1;
else if(key>arr[mid])
low=mid+1;
else if(key==arr[mid])
return mid;
else
return -1;
}
}
斐波那契查找:
首先建立一个与待查找数组长度相等的斐波那契数列;
然后计算位于待查找数组长度n位于斐波那契数列的位置,然后查看此位置的斐波那契数列的值是否大于n,如果大于n,则补齐待查找数列;
接下来设置“哨兵”的值,low,mid,high。mid=low+Fabonacci[k]-1;当待查找元素key<a[mid],high=mid-1,k=k-1。当待查找元素key>a[mid]时,low=mid+1,k=k-2,这样循环迭代,寻找key==a[mid]的成立时的mid的值。
当key==a[mid]这个条件成立时,由于前面可能对待查找数组进行扩展(ps:一般含有5个元素以上的数组,都会进行扩展),需要判断查找出的mid与原数组n的大小,若mid小于n,则查找出的结果就是mid,若mid大于等于n,则查找的结果就是n。
为了进一步理解斐波那契查找算法,对其思想进行下面的代码实现:
迭代法生成斐波那契数列:int fabonacci(int n)
{
int result;
int p_result;
int n_result;
result = p_result = 1;
while(n>2)
{
n=n-1;
n_result = p_result;
p_result = result;
result = p_result + n_result;
}
return result;
}
斐波那契查找:
int Fabonacci_find(int arr[],int key,int n)
{
int low,high,mid,i,k;
int *F;
low=0;
high=n-1;
k=0;
F=(int*)malloc(n*sizeof(int));
for(i=0;i<n;i++){
F[i]=fabonacci(i);
//printf("%d\t",F[i]);
}
//printf("\n");
while((n-1)>(F[k]-1))
k++;
for(i=n-1;i<F[k]-1;i++)
arr[i]=arr[n-1];
while(low<=high)
{
mid=low+F[k-1]-1;
if(key<arr[mid])
{
high=mid-1;
k=k-1;
}
else if(key>arr[mid])
{
low=mid+1;
k=k-2;
}
else
{
if(mid<=n-1)
{
free(F);
return mid;
}
else
{
free(F);
return n-1;
}
}
}
free(F);return 0;
}
实现这三种查找算法前,都需要对数据进行排序,三种的算法复杂度大致为log(n),针对于分布均匀的数组,插值查找的性能好于折半查找,插值查找涉及到了乘法除法运算,对于大量的数据查找效率显出低效,fabonacci查找只含有加减法运算,可以节省一定的计算量。