查找表是由同一类型的数据元素(或记录)构成的集合。
查找表按照操作方式分有两大类:静态查找表和动态查找表。
静态查找表:只作查找操作的查找表。主要操作有:
(1)查询某个“特定的”数据元素是否在查找表中。
(2)检索某个“特定的”数据元素和各种属性。
动态查找表:在查找过程中同时插入查找表中不存在的数据元素,或者从查找表中删除已经存在的某个数据元素。主要操作:
(1)查找时插入数据元素。
(2)查找时删除数据元素。
顺序查找:
顺序查找又叫线性查找,是最基本的查找技术,它的查找过程是:从第一个(或者最后一个)记录开始,逐个进行记录的关键字和给定值进行比较,若某个记录的关键字和给定值相等,则查找成功。如果查找了所有的记录仍然找不到与给定值相等的关键字,则查找不成功。
顺序查找算法的时间复杂度是O(n)。
斐波那契查找(黄金分割法查找):
黄金比例又称黄金分割,是指事物各部分间一定的数学比例关系,即将整体一分为二,较大部分与较小部分之比等于整体与较大部分之比,其比值约为1:0.618或1.618:1。
0.618被公认为最具有审美意义的比例数字,这个数值的作用不仅仅体现在诸如绘画、雕塑、音乐、建筑等艺术领域,而且在管理、工程设计等方面也有着不可忽视的作用。因此被称为黄金分
割。
随着斐波那契数列的递增,前后两个数的比值会越来越接近0.618,利用这个特性,我们就可以将黄金比例运用到查找技术中。
要点:
(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>