折半查找又称二分查找,仅使用于有序的顺序表。基本思想是:
将给定值与表中中间位置的元素比较,若相等则查找成功,返回该元素的存储位置;若不等则所需查找的元素只能在中间元素以外的前半部分或后半部分。在缩小的范围内重复进行同样的查找直到找到为止,或确定表中没有所需要查找的元素,返回查找失败的信息。
要获得有序的顺序表,可以使用qsort来排序,简要介绍使用方法:
#include <stdlib.h> void qsort(void *buf,size_t num,size_t size,int (*compare)(const void *,const void *)); //buf:要排序数组的起始地址,也可以是指针,申请了一块连续的堆空间 //num:数组中元素的个数 //size:数组中每个元素所占用的空间大小 //compare:比较规则,需要我们传递一个函数名,这个函数由我们自己编写,返回值必须是int类型,形参是两个void类型指针,这个函数是qsort内部调用的,相当于我们传递一种行为给qsort
折半查找的流程是:
- 初始化顺序表为随机10个元素;
- 使用qsort进行排序并打印;
- 输入要查找的元素值到变量key中;
- 通过二分查找找对应key值,并输出找到或未找到信息。
需要注意的是,虽然复用了顺序查找的部分代码,但折半查找并不需要使用哨兵,注意细节之处。
下面练习:实现折半查找,即自建一个顺序表并排序后实现折半查找。
1. 定义
//折半查找(只适用于顺序表),又称二分查找
typedef int ElemType;
typedef struct {
ElemType *elem;
int TableLen;//存储动态数组里元素的个数
}SSTable;
2. 顺序表初始化
//顺序表随机初始化10个元素
void ST_Init(SSTable &ST,int len){
//顺序查找时使用了哨兵,此处实现时不需要使用哨兵
ST.TableLen=len;
ST.elem=(ElemType*)malloc(sizeof(ElemType)*ST.TableLen);
int i;
srand(time(NULL));//随机数生成
for(i=0;i<ST.TableLen;i++){//第0个是哨兵,所以从1随机
ST.elem[i]=rand()%100;//随机生成的数都在0-99之间
}
}
3. 打印顺序表
//打印顺序表
void ST_print(SSTable ST){
int i;
for (i = 0; i<ST.TableLen ; i++) {
printf("%3d",ST.elem[i]);
}
printf("\n");
}
4. 折半查找
//二分查找,时间复杂度log n
int BinarySearch(SSTable L,ElemType key){
int low=0;
int high=L.TableLen-1;
int mid;
while(low<=high){//可以让mid既能取到low,也能取到high
mid=(low+high)/2;
if(key>L.elem[mid]){//如果目标大于中位数
low=mid+1;
}else if(key<L.elem[mid]){
high=mid-1;
}else{
return mid;//等于key就找到了
}
}
return -1;
}
5. 排序实现
//函数名中存储的是函数的入口地址,也是一个指针,是函数指针类型
//left和right指针指向数组中的任意两个元素的地址
//qsort规定如果left指针指向的值大于right指针指向的值,返回正值,小于返回负值,等于返回0
int compare(const void *left,const void *right){
return *(ElemType *)left-*(ElemType *)right;//从小到大排序
//return *(ElemType*)right-*(ElemType*)left;//从大到小排序
}
6. 主函数
int main() {
SSTable ST;
ST_Init(ST,10);
ST_print(ST);//打印顺序表中元素
qsort(ST.elem,ST.TableLen, sizeof(ElemType),compare);//qsort实现的是快速排序
ST_print(ST);//再次打印
ElemType key;
printf("input search key:");
scanf("%d",&key);
int pos;
pos=BinarySearch(ST,key);
if(pos!=-1){
printf("BinarySearch find key %d\n",pos);
} else{
printf("BinarySearch don't find key\n");
}
return 0;
}
7. 测试
最后,1024程序员节快乐~