stl——二分查找

本文介绍了STL中两种二分查找函数upper_bound和lower_bound的使用方法,并通过实例展示了如何确定特定值在有序数组中的插入位置。upper_bound用于找到大于指定值的第一个元素位置,而lower_bound则用于找到大于等于指定值的第一个元素位置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在stl中对二分查找进行了封装,有两种——upper_bound,lower_bound。

例如:pos=lower_bound(a,a+n,value);///查找value值在长度为n的数组a中的位置

关于返回值,函数lower_bound()在first和last中的前闭后开区间进行二分查找,返回大于或等于val的第一个元素位置。如果所有元素都小于val,则返回last的位置

upper_bound返回大于val的第一个元素位置

#include<iostream>
#include <algorithm>//必须包含的头文件
using namespace std;

int main(){
 int point[10] = {1,3,7,7,9};
 int tmp = upper_bound(point, point + 5, 7) -point;//按从小到大,7最多能插入数组point的哪个位置
 printf("%d\n",tmp);
 tmp = lower_bound(point, point + 5, 7) -point;////按从小到大,7最少能插入数组point的哪个位置
 printf("%d\n",tmp);
 return 0;
}

output:

4

2






革命尚未成功!

### 关于二分查找算法的实现与解释 #### 一、二分查找的核心概念 二分查找是一种高效的查找算法,适用于已排序的数据集合。其核心思想是通过断缩小搜索范围,每次排除掉一半的可能性,从而快速定位目标值的位置。该算法的时间复杂度为 \( O(\log n) \),空间复杂度为 \( O(1) \)[^3]。 --- #### 二、两种常见的二分查找实现方式 ##### 1. 非递归版本(迭代实现) 这是最常用二分查找实现方法之一。以下是基于 Java 的具体实现: ```java public class Main { public static void main(String[] args) { int[] a = {1, 3, 5, 7, 9}; System.out.println(binarySearch(a, 9)); } // 参数分别表示查找数组和查找目标,返回值是查找到的位置,未查找到则返回 -1 public static int binarySearch(int[] a, int target) { int i = 0, j = a.length - 1; while (i <= j) { // 计算中间索引,防止溢出使用位运算代替除法 int m = (i + j) >>> 1; if (target > a[m]) { i = m + 1; } else if (target < a[m]) { j = m - 1; } else { return m; // 找到目标值 } } return -1; // 未找到目标值 } } ``` 这种实现方式的关键在于边界条件的处理以及如何更新 `i` 和 `j` 的值[^1]。 --- ##### 2. 另一种非递归版本 另一种常见的方式稍微调整了边界的定义,使得逻辑更加清晰。下面是其实现代码: ```java public static int binarySearch2(int[] a, int target) { int i = 0, j = a.length; while (i < j) { int mid = (i + j) >>> 1; if (target > a[mid]) { i = mid + 1; } else if (target < a[mid]) { j = mid; } else { return mid; // 找到目标值 } } return -1; // 未找到目标值 } ``` 这种方式的主要区别在于初始时将 `j` 定义为数组长度而非最后一位索引,这有助于简化某些特殊情况下的判断逻辑[^1]。 --- #### 三、递归版本的二分查找 除了迭代实现外,还可以采用递归来完成二分查找。虽然递归会引入额外的栈开销,但在理解算法结构方面非常直观。以下是 Python 中的一个例子: ```python def binary_search_recursive(arr, target, left, right): if left > right: return -1 # 基本情况:未找到目标值 mid = (left + right) // 2 if arr[mid] == target: return mid # 找到目标值 elif arr[mid] < target: return binary_search_recursive(arr, target, mid + 1, right) # 在右侧继续查找 else: return binary_search_recursive(arr, target, left, mid - 1) # 在左侧继续查找 # 测试用例 arr = [1, 3, 5, 7, 9] print(binary_search_recursive(arr, 9, 0, len(arr) - 1)) ``` 递归版本的优点是可以更清楚地展示算法的工作流程,缺点则是可能会因深层调用而导致性能下降或堆栈溢出。 --- #### 四、二分查找的应用场景 二分查找仅限于简单的数值查找,还广泛应用于各种实际问题中。例如,在 C++ STL 中,函数 `lower_bound` 和 `upper_bound` 就是基于二分查找的思想设计的。下面是一个典型的例子——寻找插入位置: ```cpp class Solution { public: int searchInsert(std::vector<int>& nums, int target) { int left = 0, right = nums.size() - 1; while (left < right) { int mid = left + (right - left) / 2; if (nums[mid] < target) { left = mid + 1; } else { right = mid; } } if (nums[left] >= target) return left; else return left + 1; } }; ``` 这段代码展示了如何利用二分查找解决“插入位置”的问题,即在一个有序数组中确定某个值应该放置的位置[^2]。 --- #### 五、总结 无论是哪种实现方式,二分查找都依赖于数据集已经排序的前提条件。它的高效性和简洁性使其成为许多编程竞赛和工程实践中的重要工具。然而需要注意的是,当面对动态变化的数据或者无法预知大小的情况时,可能需要考虑其他更适合的解决方案。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值