折半查找是将有序的数列不断的缩小一半,直到找到该元素或者折半区域的首元素位置高于尾元素的位置为止。即将数列按有序化(递增或递减)排序,查找过程中采用跳跃方式查找,先以有序数列的中点位置为比较对象,如果要查找的元素值小于改中点元素,则将带查序列缩小为左半部分,否则为右半部分,通过一次比较,将查找区间缩小一半,如此循环直到最后找到元素或者未找到元素。更详细解释看这里。
开发思路
折半查找是一种高效的查找方式,可以明显的减少比较次数,提高查找的效率。但是折半查找的先决条件是查找表中的所有数据元素必须的有序的。实现思路如下:
首先我们需要设置3个变量low,mid,high分别保存数组元素的开始,中间,结尾的位置序号。假定有10个元素,开始时low=0,mid = (low+high)/2,high=9.接下来进行判断
1)如果位置为mid所对应的元素值与我们要查找的值x相等,表示查找到了该元素,立即返回位置序号mid。
2)否则,如果查找值x<a[mid],表示要查找的数据x位于low与mid-1位置序号之间,就不在需要去查找mid与high位置序号之间的元素了。因此将high变量的值改为mid-1,重新开始查找low与high之间的数据。
3)如果x>a[mid],表示要查找的数据元素的值大于中间位置值,那么元素必定位于mid+1和high位置序号之间,也就不需要再去查找low与mid之间的元素了。因此将low变量的值改为mid-1,重新查找low到high之间的数据。
4)逐步循环,如果到了low>high,那么表示查不到目标元素x,即数组中无该数据。
简单例子
使用折半查找,根据提示输入10个有序的数列和想要查找的关键字,程序会输出所要查找的关键字在数组中的位置。
C语言-while循环
#include <stdio.h>
int search(int a[], int n, int x)
{
int low,mid,high;
low = 0;
high = n-1;
while (low<=high) {
mid = (low+high)/2;
if (a[mid]==x) {
return a[mid];
} else if (a[mid]>x) {
high = mid-1;
} else {
low = mid+1;
}
}
return -1;
}
int main(int argc, const char * argv[]) {
int i,x,z;
int a[10];
printf("请输入10个有序的数\n");
for (i=0; i<10; i++) {
scanf("%d", &a[i]);
}
printf("请输入要查找的数");
scanf("%d", &x);
z = search(a, 10, x);
if (z) {
printf("要查找的数%d在数组中的位置是第%d个元素\n", x,z);
} else {
printf("要查找的元素%d不在数组中\n",x);
}
return 0;
}
C语言-递归
int binarySearch(int a[], int start, int end, int key)
{
if (start > end) { return -1; }
int mid = start + (end - start) / 2;
if (a[mid] > key) {
return binarySearch(a, start, mid - 1, key);
} else if (a[mid] < key) {
return binarySearch(a, mid + 1, end, key);
} else {
return mid;
}
}
Swift版本
/// 二分搜索完全匹配
///
/// - Parameters:
/// - arr: 有序数组
/// - start: 起始位置
/// - end: 结束点
/// - khey: 特点目标值
/// - Returns: 返回查找结果
func binarySearch(arr: [Int], start: Int, end: Int, key: Int) -> Int? {
guard start < end else {
return nil
}
let mid = start + (end - start) / 2
if arr[mid] > key {
return binarySearch(arr: arr, start: start, end: mid - 1, key: key)
} else if arr[mid] < key {
return binarySearch(arr: arr, start: mid + 1, end: end, key: key)
} else {
return mid
}
}