📌  相关文章
📜  C++中对向量中lower_bound()和upper_bound()的实现(1)

📅  最后修改于: 2023-12-03 14:39:56.607000             🧑  作者: Mango

C++中对向量中lower_bound()和upper_bound()的实现

在C++中,lower_bound和upper_bound是STL库提供的两个非常有用的函数,它们可以帮助程序员在已排好序的数组或容器中找到某个元素的位置,或者返回一个迭代器范围。本文将介绍lower_bound和upper_bound的实现以及它们的应用。

lower_bound

lower_bound函数的作用是在已排序的容器中查找给定值的第一个位置,如果目标值存在,则返回目标值的位置;不存在,则返回离目标值最近的比它大的值的位置。

下面是lower_bound的实现:

template<typename ForwardIterator, typename T>
ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, const T& target)
{
    while(first < last)
    {
        auto mid = first + (last - first) / 2;
        if (*mid < target)
            first = mid + 1;
        else
            last = mid;
    }
    return first;
}

该函数接收三个参数,分别为要查找的容器的起始和结束迭代器,以及要查找的目标值。首先,通过while循环不断缩小查找的范围,直到first >= last为止;接着,以mid作为中间位置,将容器分为两部分进行查找:如果mid所在位置的值小于目标值,则将first的位置定位到mid的右侧;否则,将last的位置定位到mid的左侧,继续缩小查找范围。最后,返回first所代表的位置。如果目标值不存在于容器中,则返回离目标值最近的比它大的值,也就是目标值所应该插入位置的迭代器。注意,要使用auto关键字来定义mid的类型,这样可以自动推导出mid的类型。

下面是lower_bound函数的用法示例:

#include <iostream>
#include <vector>

using namespace std;

int main()
{
    vector<int> arr = { 1, 3, 4, 5, 7, 9 };
    int target = 6;
    auto pos = lower_bound(arr.begin(), arr.end(), target);
    if (pos != arr.end() && *pos == target)
        cout << "Found target at position " << pos - arr.begin() << endl;
    else
        cout << "Target not found, position for insertion is " << pos - arr.begin() << endl;
    return 0;
}

该代码在已排好序的数组中查找值为6的元素。lower_bound函数返回的迭代器pos指向数组中值为7的位置,因此pos-arr.begin()等于4。根据lower_bound的定义,如果目标值不存在于容器中,则返回离目标值最近的比它大的值的位置。在这个例子中,arr[4]的值是7,离目标值6最近的比它大的值是7,因此返回的是7所在的位置。

upper_bound

upper_bound的作用是查找容器中第一个大于目标值的位置。和lower_bound的不同之处在于,如果目标值存在,则返回离目标值最近的比它大的值的位置;如果目标值不存在,则直接返回离目标值最近的比它大的值的位置。

下面是upper_bound的实现:

template<typename ForwardIterator, typename T>
ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last, const T& target)
{
    while(first < last)
    {
        auto mid = first + (last - first) / 2;
        if (target < *mid)
            last = mid;
        else
            first = mid + 1;
    }
    return first;
}

和lower_bound类似,给定首尾迭代器和目标值,upper_bound函数返回大于目标值的第一个位置。首先定义迭代器mid指向中间位置,使用while循环不断缩小查找范围,直到first >= last。当目标值小于mid所指位置时,将last定位到mid的左侧,以便在左侧查找比目标值大的值;如果目标值大于等于mid所指位置,则将first定位到mid的右侧,以便在mid的右侧查找比目标值大的值。和lower_bound不同之处在于,当目标值不存在于容器中时,upper_bound返回目标值所应该插入的位置,也就是离目标值最近的比它大的值的位置,而不是目标值所在位置的下一个位置。

下面是upper_bound函数的用法示例:

#include <iostream>
#include <vector>

using namespace std;

int main()
{
    vector<int> arr = { 1, 3, 4, 5, 7, 9 };
    int target = 6;
    auto pos = upper_bound(arr.begin(), arr.end(), target);
    if (pos != arr.end() && *pos == target)
        cout << "Found target at position " << pos - arr.begin() << endl;
    else
        cout << "Target not found, position for insertion is " << pos - arr.begin() << endl;
    return 0;
}

该代码在已排好序的数组中查找值为6的元素。upper_bound函数返回的迭代器pos指向数组中值为7的位置,因此pos-arr.begin()等于4。和lower_bound一样,如果目标值不存在于容器中,则返回离目标值最近的比它大的值的位置。在这个例子中,arr[4]的值是7,离目标值6最近的比它大的值也是7,因此返回的是7所在的位置。

总结

本文介绍了C++中对向量中lower_bound()和upper_bound()的实现。可以看出,这两个函数都使用了二分查找的原理,并通过思考如何比较目标值的大小,实现了在已排序的容器中查找目标值的位置。在实际应用中,它们既可以用于查找元素,也可以用于查找插入位置,具有非常广泛的应用。