静态查找(顺序查找,折半查找,插值查找,斐波那契查找)

查找表是由同一类型的数据元素(或记录)构成的集合。


查找表按照操作方式分有两大类:静态查找表和动态查找表。


静态查找表:只作查找操作的查找表。主要操作有:

(1)查询某个“特定的”数据元素是否在查找表中。

(2)检索某个“特定的”数据元素和各种属性。

动态查找表:在查找过程中同时插入查找表中不存在的数据元素,或者从查找表中删除已经存在的某个数据元素。主要操作:

(1)查找时插入数据元素。

(2)查找时删除数据元素。


顺序查找

顺序查找又叫线性查找,是最基本的查找技术,它的查找过程是:从第一个(或者最后一个)记录开始,逐个进行记录的关键字和给定值进行比较,若某个记录的关键字和给定值相等,则查找成功。如果查找了所有的记录仍然找不到与给定值相等的关键字,则查找不成功。

顺序查找算法的时间复杂度是O(n)。


斐波那契查找(黄金分割法查找)

黄金比例又称黄金分割,是指事物各部分间一定的数学比例关系,即将整体一分为二,较大部分与较小部分之比等于整体与较大部分之比,其比值约为1:0.618或1.618:1。

0.618被公认为最具有审美意义的比例数字,这个数值的作用不仅仅体现在诸如绘画、雕塑、音乐、建筑等艺术领域,而且在管理、工程设计等方面也有着不可忽视的作用。因此被称为黄金分
割。

斐波那契数列:1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89…….(从第三个数开始,后边每一个数都是前两个数的和)。

随着斐波那契数列的递增,前后两个数的比值会越来越接近0.618,利用这个特性,我们就可以将黄金比例运用到查找技术中。

1

要点

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

(2)对于二分查找,分割是从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)-1 = F[k] - F[k-1] - 1 = F[k-2] - 1。  

斐波那契查找的核心
  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]范围内查找。

<span style="font-family:Microsoft YaHei;">#include <stdio.h>

#define MAXSIZE 13

//顺序查找,a为数组,n为要查找的数组长度,key为要查找的关键字
int Sequential_Search(int *a,int n,int key)
{
	int i;
	for(i=0;i<n;i++)
	{
		if(a[i]==key)
			return i;
	}
	return 0;
}

//有哨兵顺序查找
int Sequential_Search2(int *a,int n,int key)
{
	int i;
	a[0]=key;		//设置a[0]为关键值,称为“哨兵”
	i=n;
	while(a[i]!=key)
		i--;

	return i;
}

//折半查找
int Binary_Search(int *a,int n,int key)
{
	int low,mid,high;
	low = 1;
	high = n;

	while(low<=high)
	{
		mid = (low+high)/2;
		if(key > a[mid])
			low = mid+1;
		else if(key < a[mid])
			high = mid-1;
		else
			return mid;
	}
	return 0;
}

//插值查找
int Interpolation_Search(int *a,int n,int key)
{
	int low,mid,high;
	low = 1;
	high = n;

	while(low<high)
	{
		mid = low+(high-low)*(key-a[low])/(a[high]-a[low]);		//插值
		if(key > a[mid])
			low = mid+1;
		else if(key < a[mid])
			high = mid-1;
		else
			return mid;
	}
	return 0;
}

//构造斐波那契数列
void Fibonacci(int *F)
{
	int i;
	F[0]=0;
	F[1]=1;

	for(i=2;i<MAXSIZE;i++)
		F[i] = F[i-1] + F[i-2];
}

//斐波那契查找
int Fibonacci_Search(int *a,int n,int key)
{
	int low,high,mid,i,k;
	int F[MAXSIZE];
	low=1;
	high=n;

	k=0;
	Fibonacci(F);

	//计算n在斐波那契数列中的位置
	while(n > F[k]-1)
		k++;

	//将不满的数值补齐
	for(i=n;i<F[k]-1;i++)
		a[i]=a[high];

	while(low <= high)
	{
		mid = low+F[k-1]-1;

		if(key < a[mid])
		{
			high = mid -1;
			k = k-1;
		}
		else if(key > a[mid])
		{
			low = mid+1;
			k=k-2;
		}
		else
		{
			if(mid <= n)
				return mid;
			else
				return n;
		}
	}
	return 0;
}

int main()
{
	int result,i;
	int n = 10;
	int a[MAXSIZE] = {0,1,16,24,35,47,59,62,73,88,99};
	

	for(i=0;i<=n;i++)
		printf("%d ",a[i]);

	result = Sequential_Search(a,n,16);
	printf("\nSequential_Search 16 :%d\n",result);

	result = Sequential_Search2(a,n,24);
	printf("Sequential_Search 24 :%d\n",result);

	result = Binary_Search(a,n,35);
	printf("Binary_Search 35 :%d\n",result);
	
	result = Interpolation_Search(a,n,47);
	printf("Interpolation_Search 47 :%d\n",result);
	
	result = Fibonacci_Search(a,n,59);
	printf("Fibonacci_Search 59 :%d\n",result);

	return 0;
}</span>



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值