文章目录
- 什么是二分查找法
- 什么是upper_bound
- lower_bound
什么是二分查找法
二分查找法(Binary Search)是一种在有序数组中查找特定元素的搜索算法。二分查找法的工作原理是通过不断将搜索区间分成两半来缩小查找的范围,每次比较中间元素与目标值,根据比较结果决定是继续在左半边还是右半边查找。
二分查找法的基本步骤如下:
- 首先,确定数组的中间位置。
- 比较中间位置的元素与目标值。
- 如果中间位置的元素正好是目标值,则搜索过程结束。
- 如果目标值小于中间位置的元素,则在数组的左半边继续搜索。
- 如果目标值大于中间位置的元素,则在数组的右半边继续搜索。
- 重复上述步骤,直到找到目标值或搜索范围为空。
在 C++ 中,你可以使用标准库中的std::binary_search
函数来检查数组或容器中是否存在某个元素,或者你可以自己实现二分查找法。以下是使用std::binary_search
的示例:
#include <iostream>
#include <vector>
#include <algorithm> // 包含 std::binary_search
int main() {
std::vector<int> vec = {1, 3, 5, 7, 9, 11, 13, 15};
int target = 7;
// 使用 std::binary_search 查找元素
bool found = std::binary_search(vec.begin(), vec.end(), target);
if (found) {
std::cout << "Element " << target << " found in the vector." << std::endl;
} else {
std::cout << "Element " << target << " not found in the vector." << std::endl;
}
return 0;
}
如果你想自己实现二分查找法,以下是代码示例:
#include <iostream>
#include <vector>
int binarySearch(const std::vector<int>& vec, int target) {
int left = 0;
int right = vec.size() - 1;
while (left <= right) {
int mid = left + (right - left) / 2; // 防止溢出
if (vec[mid] == target) {
return mid; // 找到目标值,返回索引
} else if (vec[mid] < target) {
left = mid + 1; // 在右侧子数组中查找
} else {
right = mid - 1; // 在左侧子数组中查找
}
}
return -1; // 未找到目标值,返回 -1
}
int main() {
std::vector<int> vec = {1, 3, 5, 7, 9, 11, 13, 15};
int target = 7;
int index = binarySearch(vec, target);
if (index != -1) {
std::cout << "Element " << target << " found at index " << index << "." << std::endl;
} else {
std::cout << "Element " << target << " not found in the vector." << std::endl;
}
return 0;
}
在这个示例中,binarySearch
函数实现了二分查找算法,并返回目标值在数组中的索引(如果找到的话),或者返回 -1(如果没有找到)。
什么是upper_bound
upper_bound
是 C++ 标准库中的一个函数,它用于在已排序的序列(例如 std::vector
、std::deque
、std::array
或其他支持随机访问迭代器的容器)中查找第一个大于特定值的元素的位置。当你调用 upper_bound
时,它返回一个指向该元素的迭代器,如果不存在这样的元素,则返回指向序列末尾的迭代器(即 end()
)。
具体来说,upper_bound
的功能如下:
- 它在指定的迭代器范围
[first, last)
内进行二分查找。 - 它寻找第一个位置,使得该位置上的元素大于给定的值
value
。 - 如果所有元素都不大于
value
,则返回last
(一个指向序列末尾的迭代器)。 - 如果找到了这样的元素,它返回一个指向该元素的迭代器。
这个函数要求序列在[first, last)
范围内是有序的,且序列至少部分排序为非降序(即元素可以相等,但不能出现后面的元素小于前面的元素)。
使用upper_bound
需要包含<algorithm>
头文件,并且它通常与std::sort
或其他排序函数配合使用,以确保序列是有序的。
在 C++ 中,upper_bound
是标准库中的一个函数,它用于在有序序列中查找第一个大于特定值的元素的位置。该函数定义在头文件<algorithm>
中。下面是对upper_bound(a.begin(), a.end(), x)
的详细解释: a.begin()
: 这是容器a
的开始迭代器,指向容器中的第一个元素。a.end()
: 这是容器a
的结束迭代器,指向容器中最后一个元素的下一个位置。x
: 这是你要在容器a
中查找的值。
函数upper_bound
的行为如下:
- 它在区间
[a.begin(), a.end())
中查找。 - 它寻找第一个位置,使得该位置上的元素大于
x
。 - 如果所有元素都不大于
x
,则返回a.end()
。
返回值:
- 如果找到了这样的元素,
upper_bound
返回一个指向该元素的迭代器。 - 如果没有找到,它返回一个指向
a.end()
的迭代器。
示例:
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> a = {1, 2, 4, 4, 6, 8};
int x = 4;
auto it = upper_bound(a.begin(), a.end(), x);
if (it != a.end()) {
std::cout << "第一个大于 " << x << " 的元素是:" << *it << std::endl;
} else {
std::cout << "没有找到大于 " << x << " 的元素。" << std::endl;
}
return 0;
}
在这个例子中,upper_bound
将返回指向第一个 6
的迭代器,因为 6
是第一个大于 4
的元素。如果 x
是 8
或更大的值,upper_bound
将返回 a.end()
。
lower_bound
C++ 标准库中也有 lower_bound
函数,它与 upper_bound
函数非常相似,但是它们的用途略有不同。lower_bound
用于在已排序的序列中查找第一个不小于(即大于或等于)特定值的元素的位置。
以下是 lower_bound
函数的基本行为:
- 它在指定的迭代器范围
[first, last)
内进行二分查找。 - 它寻找第一个位置,使得该位置上的元素不小于给定的值
value
。 - 如果所有元素都小于
value
,则返回last
(一个指向序列末尾的迭代器)。 - 如果找到了这样的元素,它返回一个指向该元素的迭代器。
与upper_bound
不同的是,lower_bound
寻找的是第一个大于或等于特定值的元素,而upper_bound
寻找的是第一个大于特定值的元素。
lower_bound
的使用也需要包含<algorithm>
头文件,并且序列必须是有序的。
下面是lower_bound
的一个简单示例:
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> a = {1, 2, 4, 4, 6, 8};
int x = 4;
auto it = lower_bound(a.begin(), a.end(), x);
if (it != a.end()) {
std::cout << "第一个大于或等于 " << x << " 的元素是:" << *it << std::endl;
} else {
std::cout << "没有找到大于或等于 " << x << " 的元素。" << std::endl;
}
return 0;
}
在这个例子中,lower_bound
将返回指向第一个 4
的迭代器,因为 4
是第一个不小于 4
的元素。如果 x
是 1
或更小的值,lower_bound
也将返回指向第一个 1
的迭代器。如果 x
是 9
或更大的值,lower_bound
将返回 a.end()
。