简单查找算法之折半查找、插值查找、斐波那契查找

首先看折半查找,字面意思就能看出来是什么意思。定义三个“哨兵”,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查找只含有加减法运算,可以节省一定的计算量。


  

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页