折半查找
查找前提:序列必须是有序的。
核心思想:每次都从查找范围的中间下标开始比较,如果key值偏大,因为序列式递增的,则将范围缩小至原来的右半部分,否则将范围缩小至左半部分,接着继续计算中间下标,继续比较,直至匹配关键字。
时间复杂度:O(logn)
#include<stdio.h>
int fun(int a[],int left,int right,int key){
int mid;
while(left<=right){
mid = (left+right)/2;
if(key==a[mid])
return mid;
else if(key>a[mid])
left = mid+1; //范围缩小至右半部分
else
right = mid-1; //范围缩小至左半部分
}
return 0;
}
int main(){
int a[10]={1,2,3,4,5,6,7,8,9,10};
printf("%d\n",fun(a,0,9,4));
return 0;
}
插值查找(改进的折半查找)
核心思想:原来折半查找中查找范围的中间值选取完全是根据范围左右取中间下标,与左右下标的值无关,现在改进为加入左右下标的值来计算中间下标。
时间复杂度:O(logn)
相比较于折半,当序列越大时,插值的优势越大。
#include<stdio.h>
int fun(int a[],int left,int right,int key){
int mid;
while(left<=right){
mid = left + (key-a[left])/(a[right]-a[left]) * (right - left);
if(key==a[mid])
return mid;
else if(key>a[mid])
left = mid+1;
else
right = mid-1; // key<a[mid]的情况
}
return 0;
}
int main(){
int a[10]={1,2,3,4,5,6,7,8,9,10};
printf("%d\n",fun(a,0,9,4));
return 0;
}