静态查找算法

Posted 田啊田

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了静态查找算法相关的知识,希望对你有一定的参考价值。

查找就是根据给定的某个值,在查找表中确定一个其关键字等于给定的数据元素。它又可以分为静态的和动态的查找。
在这里插入图片描述

一. 顺序表查找

顺序表查找的可以分为for循环查找和while循环查找

1.For的循环查找

int for_Search(int *a, int n, int key)
{
	int i;
	for (i = 1; i <= n; i++)
	{
		if (a[i] == key)
			return i;
	}
	return 0;
}

可知最坏的情况是key值在数组的最后一位,时间复杂度是O(n。)最好的是在第一位,为O(1)。

For顺序查找的时候会对i的值进行判断,看它是否越界,对于这个问题比较好的解决方法是设置“哨兵”在While循环就可实现。

2.while循环查找

我们可以设置在线性表的第0位就是要查找的值,称第0位为“哨兵”这样从线性表的最大的下标开始,就一定会找到我们想要的key值,最坏的情况就是该线性表中没有要找的值就会返回下标为0的情况。这样就可以不用每次对i的值进行判断,就可直接比较线性表的值与我们要找的key值。

int while_Search(int *a, int n, int key)
{
	int i;
	a[0] = key;/*设置哨兵*/
	i = n;
	while (a[i] != key)
	{
		i--;
	}
	return i;
}

这时的时间复杂度为O(n)。

二. 有序表的查找

如果把顺序表的数据按照一定的顺序排列下来,大小关系或者其他的关系,我们可以把它称为有序表,在有序表的查找中我们有折半查找,插值查找(比例查找),斐波那契查找。(这里我们查找的数组的第一位的下标设置为1)

1.折半查找

折半查找又称二分查找,它的前提就是我们要找的数据在线性表中。它就是将我们的数据对半分,再用中间的数来和我们的key值进行比较,如果小于中间的数的话就在它的下半区继续查找,否则在上半区继续查找。不断重复上述过程,直到查找成功,或者所有查找区域无记录,查找失败为止。

int Bi_search(int *a, int n, int key)/*折半查找*/
{
	int low, high, mid;
	low = 1;
	high = n;
	while (low <= high)
	{
		mid = (low + high) / 2;
		if (key < a[mid])
			high = mid - 1;
		if (key > a[mid])
			high = mid + 1;
		else
			return mid;
	}
	return 0;
}

时间复杂度即O(logn)。

2.差值查找

差值查找我也将它称为比例查找如果你观察就会发现与对半查找不同的是,在差值查找中我们是将key值与最小值得差与最大值和最小值的差的比例进行分割的。即mid(分割的下标)=(key-a[low])/(a[high]-a[low])。

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

时间复杂度为O(logn)。适用于比较长的,而key值又比较均匀的查找表中,比折半查找要好的多。

3.斐波那契查找

既然有序查找中的折半查找和差值查找都是划分要找的数组那么斐波那契查找也应该就是划分线性表的方法,斐波那契查找是利用黄金分割的原理来实现的。那么就可以得到斐波那契的线性表,如下图所示。

在这里插入图片描述

可以看到在下标等于9的时候,数值为34,也就是说在这34个数中按照前21个数,后13个数的划分来进行的,21/34约等于0.618。

这样就可以简单的知道斐波那契的思维,和其他的有序查找是一样的,只不过斐波那契线性表是用来划分我们要查找的线性表而已。

int F[100];/*假设F是我们的斐波那契线性表,它是从下标为0开始的*/
int Fi_Search(int *a, int n, int key)/*a是我们要查找的数组,n是开始用来记录数组值得个数, key就是我们要查找的值*/
{
	int i, low, high, mid, k;
	F[0]=0;
	F[1]=1;
	for(i = 2;i < 100;i++)  
	F[i] = F[i-1] + F[i-2];  
	low = 1;
	high = n;
	k = 0;
	while (n > F[k] - 1)/*计算n在斐波那契数列中的位置*/
		k++;
	for (i = n; i < F[k] - 1; i++)
		a[i] = a[n];/*将不全的数值补全*/
	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;
}

斐波那契的时间复杂度为O(logn),比较关键的一点是折半查找和差值查找都是运用了四则运算,而斐波那契查找只用到了简单的加法运算。

可以看出三种有序表的查找实质上是分割点的不同,各有优劣,实际开发中根据数据的特点综合考虑再做出选择。
后续…………………………….

int main()
{    

	int result;
	int arr[MAXSIZE]={0,1,16,24,35,47,59,62,73,88,99};
	result=for_Search(arr,10,62);
	printf("for_Search:%d \\n",result);
	result=while_Search(arr,10,62);
	printf("while_Search:%d \\n",result);
	result=Bi_Search(arr,10,62);
	printf("Bi_Search:%d \\n",result);
	result=In_Search(arr,10,62);
	printf("In_Search:%d \\n",result); 
	result=Fi_Search(arr,10,62);
	printf("Fi_Search:%d \\n",result);
	
	return 0;
}

以上是关于静态查找算法的主要内容,如果未能解决你的问题,请参考以下文章

[Algorithm]二分插值斐波那契查找算法 Java 代码实现

静态查找算法

数据结构49:顺序查找算法

数据结构(C语言版)严蔚敏--->常用的查找算法[静态查找表动态查找表]

数据结构(C语言版)严蔚敏--->常用的查找算法[静态查找表动态查找表]

静态查找算法 - 顺序查找二分查找插值查找斐波那契查找