目录
嗨,感谢你打开这篇文章!👋 如果阅读中发现任何笔误或表述不清的地方,欢迎随时留言告诉我~你的视角会让内容变得更完善!
一、二分查找法
如果我们有一组有序序列,以升序为例,我们要从这组升序序列里面查找一个数,假设我们要找的数为x,我们先将x与这组有序数列里面最中间的那个数进行比较,如果要查找的数比中间这个数小,就说明我们要查找的数在中间这个数的左边部分,我们在将要查找的数与左边部分的最中间的那个数进行比较,如果比左边部分最中间的数大,那就说明我们要查找的数在这个最中间数的右边部分,我们在将要查找的数与右边部分中间的数进行比较,重复这种方法,直到找到我们要查找的数,每次我们将要查找的数与最中间的那个数进行比较后,大于就在右边部分继续查找,小于就在左边部分查找,我们就发现每次都能缩小一半的查找范围,这种方法我们就称为二分查找法,也叫做折半查找。
基本逻辑:二分查找(Binary Search)是一种在有序数组中查找某一特定元素的查找算法。查找过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则查找过程结束;如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。如果在某一步骤数组为空,则代表找不到。
举例{5,13,19,21,37,56,64,75,80,88,92}
采用二分查找算法查找关键字为 21 的过程为:
(1)找到中间值
(2)21比中间值小,则在左半部分找中间值
(3) 比中间值大,则在右半部分找中间值
二、时间复杂度
二分查找法每次把搜索区域减少一半,时间复杂度为 O(logn)
三、C语言代码实现
1、递归实现
/*
* @brief 递归实现二分查找法查找指定元素
* @param start 需要查找部分的最左边元素的下标
* @param end 需要查找部分的最右边元素的下标
* @param key 需要查找的元素
* @return 成功返回查找到的元素的下标,失败放回FALSE
*/
int binary_search(int* arr1, int start, int end, int key)
{
if (NULL == arr1)
return FALSE;
if (start > end)//递归结束条件
return FALSE;
//需要查找部分的中间元素
int mid = (start + end) / 2;
//找到了需要查找的元素
if (key == arr1[mid])
{
return mid;
}
//如果比中间元素小,在左半部分继续查找
else if (key < arr1[mid])
{
return binary_search(arr1, start, mid - 1,key);
}
//比中间元素大,在右半部分继续查找
else
{
return binary_search(arr1, mid + 1, end, key);
}
}
2、非递归实现
/*
* @brief 非递归实现二分查找法查找指定元素
* @param start 需要查找部分的最左边元素的下标
* @param end 需要查找部分的最右边元素的下标
* @param key 需要查找的元素
* @return 成功返回查找到的元素的下标,失败放回FALSE
*/
int binary_search1(int* arr1, int start, int end, int key)
{
if (NULL == arr1)
return FALSE;
while (start <= end)
{
//需要查找部分的中间元素
int mid = (start + end) / 2;
//找到了需要查找的元素
if (key == arr1[mid])
{
return mid;
}
//如果比中间元素大,在右半部分继续查找
else if (key > arr1[mid])
{
start= mid + 1;
}
//比中间元素小,在左半部分继续查找
else
{
end = mid - 1;
}
}
return FALSE;
}
3、完整代码
#include<stdio.h>
#include<string.h>
#include <stdbool.h>
#define TRUE 0
#define FALSE -1
/*
* @brief 二分查找法查找指定元素
* @param start 需要查找部分的最左边元素的下标
* @param end 需要查找部分的最右边元素的下标
* @param key 需要查找的元素
* @return 成功返回查找到的元素的下标,失败放回FALSE
*/
int binary_search(int* arr1, int start, int end, int key)
{
if (NULL == arr1)
return FALSE;
if (start > end)//递归结束条件
return FALSE;
//需要查找部分的中间元素
int mid = (start + end) / 2;
//找到了需要查找的元素
if (key == arr1[mid])
{
return mid;
}
//如果比中间元素小,在左半部分继续查找
else if (key < arr1[mid])
{
return binary_search(arr1, start, mid - 1,key);
}
//比中间元素大,在右半部分继续查找
else
{
return binary_search(arr1, mid + 1, end, key);
}
}
/*
* @brief 二分查找法查找指定元素
* @param start 需要查找部分的最左边元素的下标
* @param end 需要查找部分的最右边元素的下标
* @param key 需要查找的元素
* @return 成功返回查找到的元素的下标,失败放回FALSE
*/
int binary_search1(int* arr1, int start, int end, int key)
{
if (NULL == arr1)
return FALSE;
while (start <= end)
{
//需要查找部分的中间元素
int mid = (start + end) / 2;
//找到了需要查找的元素
if (key == arr1[mid])
{
return mid;
}
//如果比中间元素大,在右半部分继续查找
else if (key > arr1[mid])
{
start= mid + 1;
}
//比中间元素小,在左半部分继续查找
else
{
end = mid - 1;
}
}
return FALSE;
}
int main()
{
int arr1[] = {2,4,6,8,10};
int ret = binary_search(arr1, 0, sizeof(arr1) / sizeof(arr[0]) - 1, 4);
printf(" %d\n", ret);
int ret1 = binary_search1(arr1, 0, sizeof(arr1) / sizeof(arr[0]) - 1, 2);
printf(" %d\n", ret1);
return 0;
}