本实例采用二分查找法查找特定关键字的元素。要求用户输入数组长度,也就是有序表的数据长度,并输入数组元素和査找的关键字。程序输出查找成功与否,以及成功时关键字在数组中的位置。例如,在有序表 11、13、18、 28、39、56、69、89、98、122 中査找关键字为 89 的元素。
算法表述:
折半查找法也叫做二分查找,顾名思义,就是把数据分成两半,再判断所查找的key在哪一半中,再重复上述步骤知道找到目标key;
注意:(咳咳,敲黑板)折半查找法仅适用于对已有顺序的数组、数据进行操作!!!
折半查找只能在有序数列中进行,将待查找的数据与有序数列(递增)中间的元素进行比较,如果相等,则找到;如果待查找的数据大于中间的元素的值,那么再从数组的后一半元素中进行查找,否则,从前一半元素中进行查找;若折半后都找不到,则输出“没找着”等提示信息。
算法执行过程分析:
例如:要在数组arr[]={8,7,9,6,4,1,2,5,3,10,11};中查找key=7的位置;首先,我们要先将数组arr中的数据成员进行排序。arr[]={1,2,3,4,5,6,7,8,9,10,11};
如图所示:将该组数据小端记作low,大端记作high,中间值记作mid;
二分法查找时,将所查找的key与mid比较,例如key=7,即可缩小查找范围在mid和high之间;
如图所示即可找到key=low=7;
注意:(敲黑板)如果中间数mid不是整数,需要进行取整。
实现过程:
(1) 自定义函数 binary_search(),实现二分査找。
(2) main() 函数作为程序的入口函数。程序代码如下:
#include <stdio.h>
int binary_search(int key, int a[], int n) { //自定义函数binary_search()
int low, high, mid, count = 0, count1 = 0;
low = 0;
high = n - 1;
while (low < high) //査找范围不为0时执行循环体语句
{
count++; //count记录査找次数
mid = (low + high) / 2; //求中间位置
if (key < a[mid]) //key小于中间值时
high = mid - 1; //确定左子表范围
else if (key > a[mid]) //key 大于中间值时
low = mid + 1; //确定右子表范围
else if (key == a[mid]) //当key等于中间值时,证明查找成功
{
printf("查找成功!\n 查找 %d 次!a[%d]=%d", count, mid, key); //输出査找次数及所査找元素在数组中的位置
count1++; //count1记录查找成功次数
break;
}
}
if (count1 == 0) //判断是否查找失敗
printf("查找失敗!"); //査找失敗输出no found
return 0;
}
int main() {
int i, key, a[100], n;
printf("请输入数组的长度:\n");
scanf("%d", &n); //输入数组元素个数
printf("请输入数组元素:\n");
for (i = 0; i < n; i++)
scanf("%d", &a[i]); //输入有序数列到数组a中
printf("请输入你想查找的元素:\n");
scanf("%d", &key); //输入要^找的关键字
binary_search(key, a, n); //调用自定义函数
printf("\n");
return 0;
}
输出结果:
请输入数组的长度:
10
请输入数组元素:
2 3 5 6 8 10 12 13 15 18
请输入你想查找的元素:
8
查找成功!
查找 1 次!a[4]=8
方法二:
int BinSearch(int arr[], int len, int key) { //折半查找法(二分法)
int low = 0; //定义初始最小
int high = len - 1; //定义初始最大
int mid; //定义中间值
while (low <= high) {
mid = (low + high) / 2; //找中间值
if (key == arr[mid]) //判断min与key是否相等
return mid;
else if (key > arr[mid]) //如果key>mid 则新区间为[mid+1,high]
low = mid + 1;
else //如果key<mid 则新区间为[low,mid-1]
high = mid - 1;
}
return -1; //如果数组中无目标值key,则返回 -1 ;
}
void main() {
int a[] = {2, 3, 5, 6, 8, 10, 12, 13, 15, 18};//二分搜索是已排好序
int i, n, addr;
printf("the array is:\n");
for (i = 0; i < sizeof(a) / sizeof(int); i++)
printf("%-4d", a[i]);
printf("\nsearch number is:");
scanf("%d", &n);
addr = BinSearch(a, sizeof(a) / sizeof(int), n);
if (-1 == addr)
printf("can't find!\n");
else
printf("the %d is %dth at the array.\n", n, addr);
}
输出结果:
the array is:
2 3 5 6 8 10 12 13 15 18
search number is:8
the 8 is 4th at the array.
技术要点:
·二分査找就是折半查找,其基本思想是:首先选取表中间位置的记录,将其关键字与给定关键字 key 进行比较,若相等,则査找成功;若 key 值比该关键字值大,则要找的元素一定在右子表中,则继续对右子表进行折半查找:若 key 值比该关键宇值小,则要找的元素一定在左子表中,继续对左子表进行折半査找。如此递推,直到査找成功或査找失败(或査找范围为 0)。