二分查找 折半查找(Binary Search) |
---|
折半查找算法的基本前提: 1)采用物理线性结构存储; 2)数据必须有序。
思想: 首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。 折半查找法也称为二分查找法,它充分利用了元素间的次序关系,采用分治策略,可在最坏的情况下用O(log2n)完成搜索任务。它的基本思想是,将n个元素分成个数大致相同的两半,取a[n/2]与欲查找的x作比较,如果x=a[n/2]则找到x,算法终止。如 果x<a[n/2],则我们只要在数组a的左半部继续搜索x(这里假设数组元素呈升序排列)。如果x>a[n/2],则我们只要在数组a的右 半部继续搜索x。
时间复杂度 时间复杂度无非就是while循环的次数! 总共有n个元素,渐渐跟下去就是n,n/2,n/4,....n/2^k(接下来操作元素的剩余个数),其中k就是循环的次数 由于你n/2^k取整后>=1 即令n/2^k=1 可得k=log2n,(是以2为底,n的对数) 所以时间复杂度可以表示O(h)=O(log2n) log(2_10) log以2为底10的对数=3表示:在有10个数据组成的数组中查找一个数据,最多只需要找3次
|
本次算法学到的知识: rand()产生随机数 可以通过变换产生任意数值的随机数 最简单的升序排序 |
中心代码:
//找到了输出下标,没找到输出特定符号NOT_FOUND
int BinarySearch(int *array, int cnt, int num){
int h = 0; //head
int t = cnt - 1; //tail
int mid;
// int mid = (h+t)/2;
//小错误:将mid写在这个位置,num每次都和一个固定的值进行比较,将会进入死循环
while(h <= t){
mid = (h+t)/2;
if(num > array[mid]){
h = mid + 1;
}else if(num < array[mid]){
t = mid - 1;
}else{
return mid;
}
}
return NOT_FOUND; //#define NOT_FOUND -1
}
完整代码如下:
//折半查找完整代码
//(1)产生n个随机数 (整型正整数,且数据无规律)
//(2)将这n个数据进行升序排序
//(3)待查数据为num,利用BinarySearch进行查找
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#include<time.h>
#define NOT_FOUND -1
int *initArray(int cnt);
void showArray(int *array, int cnt);
void sortAscending(int *array, int cnt);
int BinarySearch(int *array, int cnt, int num); //找到了输出下标,没找到输出特定符号NOT_FOUND
void resultOfBinarySearch(int index);
void resultOfBinarySearch(int index){
if(index == -1){
printf("没有找到该数值\n");
}else{
printf("您要查找的数在下标为%d的位置\n", index);
}
}
//找到了输出下标,没找到输出特定符号NOT_FOUND
int BinarySearch(int *array, int cnt, int num){
int h = 0; //head
int t = cnt - 1; //tail
int mid;
// int mid = (h+t)/2;
while(h <= t){
mid = (h+t)/2;
if(num > array[mid]){
h = mid + 1;
}else if(num < array[mid]){
t = mid - 1;
}else{
return mid;
}
}
return NOT_FOUND; //#define NOT_FOUND -1
}
void sortAscending(int *array, int cnt){
int i;
int j;
int tmp;
for(i = 0; i < cnt; i++){
for(j = i + 1; j < cnt; j++){
if(array[i] > array[j]){
tmp = array[i];
array[i] = array[j];
array[j] = tmp;
}
}
}
}
void showArray(int *array, int cnt){
int i;
for(i = 0; i < cnt; i++){
printf("%d ", array[i]);
}
printf("\n");
}
int *initArray(int cnt){
int *p;
int i;
p = (int *)malloc(sizeof(int) * cnt);
srand(time(NULL));
for(i = 0; i < cnt; i++){
*(p+i) = rand()%900 + 100; //产生一个三位数的随机数,即100-999
}
return(p);
}
void main(void){
int *array; //为什么不是数组?因为要动态申请空间
int elementCount;
int number;
int index;
printf("\n请输入数组元素个数:");
scanf("%d", &elementCount);
array = initArray(elementCount);
printf("产生的%d个三位数的随机数为:", elementCount);
showArray(array, elementCount);
sortAscending(array, elementCount);
printf("这%d个数按升序排序后的结果为:", elementCount);
showArray(array, elementCount);
printf("\n请输入要查找的数:");
scanf("%d", &number);
index = BinarySearch(array, elementCount, number);
resultOfBinarySearch(index);
free(array); //千万不要忘记free
}