学习折半查找,插值查找和斐波那契查找笔记
折半查找,插值查找和斐波那契查找的前提都是要查找的数据进行了排序,他们的思想都是差不多的,只不过是mid的值不一样。
折半查找就是先查找中间的数,如果中间的数是要查找的值,那么就直接返回,否则比较中间的值与low和high的值的大小然后改变low或者high,继续查找。就直接上代码吧
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int search(int *array,int n,int a)
{
int low=0,high=n-1,mid;
while(low<=high)
{
//插值查找
mid=low+(a-array[low])/(array[high]-array[low])*(high-low); //当mid=(low+high)/2 时是折半查找
if(a==array[mid])
{
return mid;
}
if(a>array[mid])
{
low=mid+1;
}
if(a<array[mid])
{
high=mid-1;
}
}
return -1;
}
int main()
{
int array[]={1,2,4,8,10,12,26,56};
int a,local;
printf("输入要查找的数:\n");
scanf("%d",&a);
local=search(array,8,a);
if(-1==local)
{
printf("不存在\n");
}
else
{
printf("位置在:%d \n",local);
}
return 0;
}
说一下斐波那契查找,这又叫做黄金比例查找。这是因为随着斐波那契数列的增加前后两个数的比值就越接近0.618,这个0.618就是黄金比例了,就用这个特点吧折半查找中的mid的值变一下
图片中整个数组的长度是F[k]-1(其中F[k]是斐波那契数列中第k个元素的值因为是从0开始的,所以减1) 因为F[k]=F[k-1]+F[k-2],所以我们把要查找的数列分为两部分一部分是F[k],一部分是F[k-2],所以这个分割点mid就是黄金分割点,这时候会有个问题,就是我们要查找的数组的长度和斐波那契数列里面的值不一样怎么办,那么我们就延长数组(不能减少,减少查的就不完整了啊),并且把数组的最后的值赋给延长的。例如我们要查找的数组长度是10,我们要用这个方法就要把数组延长到13(因为13在斐波那契数列中而且离10最近) 上代码:
#include<stdio.h>
#define SIZE 10
//建立斐波切那数列
void CreateFib(int *fib,int size)
{
int i;
fib[0]=1;
fib[1]=1;
for(i=2;i<size;i++)
{
fib[i]=fib[i-1]+fib[i-2];
}
}
//查找
int FibSearch(int *array,int len,int a) //a是要查找的值
{
int low,high,mid,i,k;
int fib[SIZE];
low=0;
high=len-1;
CreateFib(fib,SIZE);
k=0;
//找到k的值,也就是离我们要查找数组长度最近的而且大于这个数组长度的斐波那契数列的值
while(high>fib[k]-1)
{
k++;
}
//延长数组,并把数组最后的值赋给延长了的元素
for(i=len;i<=fib[k]-1;i++)
{
array[i]=array[high];
}
while(low<=high)
{
//看图,前面的长度是fib[k-1]-1
mid=low+fib[k-1]-1;
if(a==array[mid])
{
if(mid<=len-1)
{
return mid;
}
else //说明要查找的是最后一个
{
return len-1;
}
}
if(array[mid]>a)
{
high=mid-1;
k=k-1; //k-1这块看图,前边的长度是fib[k-1],也就是下次的总长度了
}
if(array[mid]<a)
{
low=mid+1;
k=k-2; //如果进这个if k-2这块看图,后边边的长度是fib[k-2],也就是下次的总长度了
}
}
return -1;
}
int main()
{
int array[]={1,2,4,8,10,12,26,56};
int a,b;
printf("输入要查找的数:\n");
scanf("%d",&a);
b=FibSearch(array,8,a);
printf("位置在:%d\n",b);
return 0;
}