學習折半查找,插值查找和斐波那契查找筆記
折半查找,插值查找和斐波那契查找的前提都是要查找的數據進行了排序,他們的思想都是差不多的,只不過是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;
}