C语言————二分法
在 C++ 中,二分法(Binary Search)是一种用于在有序数组中查找特定元素的高效算法。
基本原理:
二分法的核心思想是利用数组的有序性,每次将搜索区间缩小一半。它通过比较目标值与区间中间元素的值来决定下一步的搜索方向,直到找到目标值或者确定目标值不存在于数组中。
例如【1,2,3】我们查找3,mid(一半的位置,也可以叫中间位置)是2,并且2<3,如果3存在于数组中,那一定在2的右边(此过程中我们将数组均匀的一分为二,并找出目标值可能存在的那一半,然后舍弃另一半),这是让区间缩小,左边界改为mid+1(或者mid)重新查找并找到了3.
在中学数学中,曾使用二分法寻找0点,也是使用分割区间的方法来寻找0点可能存在的子区间。
算法步骤:
-
初始化:设置两个指针,
left和right,分别指向数组的起始位置和结束位置。 -
计算中间位置:在每次循环中,计算中间位置
mid,通常使用公式mid = left + (right - left) / 2。(本质上还是(l+r)/2,先多减再回加可以避免l+r过大的情况)这样可以避免left和right相加时可能出现的溢出问题。 -
比较中间元素与目标值
- 如果中间元素
arr[mid]等于目标值target,则表示找到了目标,返回mid。 - 如果
arr[mid]大于target,说明目标值在左半部分,更新right = mid - 1,继续在左半区间搜索。 - 如果
arr[mid]小于target,说明目标值在右半部分,更新left = mid + 1,继续在右半区间搜索。
4.循环执行:重复步骤 2 和 3,直到 left 大于 right,此时表示目标值不在数组中,返回 -1 或其他表示未找到的标识。
代码实现:
迭代实现:
int binarySearch(int arr[], int left, int right, int target) {
while (left <= right) {
int mid = left + (right - left) / 2;
if (arr[mid] == target) {
return mid; // 找到目标元素,返回其索引
} else if (arr[mid] < target) {
left = mid + 1; // 目标元素在右半部分
} else {
right = mid - 1; // 目标元素在左半部分
}
}
return -1; // 未找到目标元素
}
递归实现:
int binarySearchRecursive(int arr[], int left, int right, int target) {
if (left <= right) {
int mid = left + (right - left) / 2;
if (arr[mid] == target) {
return mid; // 找到目标元素,返回其索引
} else if (arr[mid] < target) {
return binarySearchRecursive(arr, mid + 1, right, target); // 目标元素在右半部分
} else {
return binarySearchRecursive(arr, left, mid - 1, target); // 目标元素在左半部分
}
}
return -1; // 未找到目标元素
}
总代码举例:
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int binarySearch(vector<int>& arr, int target) {
int left = 0;
int right = arr.size() - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (arr[mid] == target) {return mid;}
else if (arr[mid] > target) {right = mid - 1;}
else {left = mid + 1;}
}
return -1;
}
int main() {
vector<int> arr = {1, 3, 5, 29, 7, 9, 11, 13, 15};
sort(arr.begin(), arr.end());//从小到大排序
int target = 7;
int result = binarySearch(arr, target);
cout << result << endl;
return 0;
}
算法分析:
复杂度分析
复杂度:
- 时间复杂度:二分法每次迭代都将搜索区间减半,因此时间复杂度为 O(log n),其中 n是数组的元素数量。这使得二分法在处理大规模有序数据时非常高效。
- 空间复杂度:在基本的二分法实现中,只需要几个额外的变量来跟踪搜索区间,因此空间复杂度为 O(1)。
O(log n)的由来:这个查找过程会一直持续,也就会一直除以2,直到我们找到目标元素或者确定目标元素不存在于数组中。当查找范围缩小到只剩下 1 个元素时,就不能再继续二分了,此时可以认为查找结束。即当时,查找过程停止。 n=
,k=
所以二分法的时间复杂度就表示为O(log n)。
应用场景:
-
在有序数组中查找元素:这是二分法最常见的应用,快速确定某个元素是否存在于数组中,并获取其位置。
-
求解方程的根:通过不断缩小根所在的区间范围,逼近方程的解。
-
优化问题:例如在寻找最优解的过程中,通过二分搜索来逐步缩小可能的解空间。
通过改变mid是>=还是>(或者<=和<)在解决存在多个相同的目标值的问题时可以改变mid最终是在这一组目标值的左边还是右边 。

浙公网安备 33010602011771号