矢量中的自定义二叉搜索

Custom binary search in vector

本文关键字:搜索 自定义      更新时间:2023-10-16

假设我有一个vector<int> myVec。让其中有n元素。我知道这些元素是按排序顺序(升序)排列的,而且它们是唯一的。设 n = 10myVec 为 {2, 4, 6, 8, 10, 12, 14, 16, 18, 20}。我得到了lr,以至于0<=l<=r<=n-1.现在我想搜索由边界l定义的子向量val的元素,并r这样

  1. 如果找到val则返回val
  2. 如果未找到val则返回(如果可能)子向量中的值,该值仅小于val
  3. 如果上述任一情况都不可能,则返回 false(或 -1)。

在上述情况下,如果l = 3r = 5.子向量是 {8, 10, 12}。如果val = 8则返回 8。如果val = 7返回 false(或 -1),则返回 false(或 -1)。如果val = 9返回 8。

我该如何实现这一点。我想要与二进制搜索相当的顺序。另外,是否可以使用algorithm头文件下存在的std::binary_search()

这样的东西?

int search(int l, int r, int value) {
  if (l > vec.Size() || r > vec.Size() || l > r) return -1;
  for (int i = r; i >= l; --i) {
    int v = vector[i];
    if (v <= value) return v;
  }
  return -1;
}

还是需要二进制?

int BinarySearch(int l, int r, int value) {
  return PrivateBinarySearch(l, r, (l+r)/2, value);
}
int PrivateBinarySearch(int l, int r, int index, int value) {
  if (vector[index] == value) return value;
  else if (vector[index] > value) {
    if (index == l) return -1;
    else if (index == r) return -1;
    else return PrivateBinarySearch(l, index, (index-1+l)/2, value);
  }
  else { // vector[index] < value
    if (index == l) return vector[index];
    else if (index == r) return vector[index];
    else return PrivateBinarySearch(index, r, (index+1+r)/2, value);
  }

希望这有帮助

这应该适合您,并且非常可扩展和灵活:

template<typename T>
typename vector<T>::const_iterator 
find_or_under (typename vector<T>::const_iterator start, typename vector<T>::const_iterator end, 
                const T& val)
{
    auto el = std::lower_bound(start, end, val);
    //if not found, propagate
    if (el == end)
        return el;
    //if it's equal, just return the iterator
    if ((*el) == val)
        return el;
    //if there is no value of an equal or smaller size, return the end
    if (el == start)
        return end;
    //otherwise, return the previous element
    return el-1;
}
//Functor representing the search
struct CustomSearch
{
    //Create a searcher from a subrange
    CustomSearch (const vector<int> &v, size_t l, size_t r)
    {
        start = std::lower_bound(std::begin(v), std::end(v), l);
        end = find_or_under(start, std::end(v), r) + 1;
    }
    //Calling the searcher
    //Returns this->end on not found
    auto operator() (int val)
    {
        return find_or_under(start, end, val);
    }
    vector<int>::const_iterator start;
    vector<int>::const_iterator end;
};
int main() {
    vector<int> v =  {2, 4, 6, 8, 10, 12, 14, 16, 18, 20};
    CustomSearch searcher {v, 3, 8};
    cout << *searcher(6);
}

使用传统的二叉搜索,稍作修改:

#include <iostream>
#include <vector>

int search(const std::vector<int> &vec, int l, int r, int val)
{
        int pivot, xl = l, xr = r, mid;
        do {
                /* Not exact match, check if the closest lower match is in the 
                 * subvector. */
                if (xl > xr) {
                        return xr >= l ? vec[xr]: -1;
                }
                mid = (xl + xr) / 2;
                pivot = vec[mid];
                if (val < pivot) {
                        xr = mid - 1;
                } else if (val > pivot) {
                        xl = mid + 1;
                } else if (val == pivot) {
                        return val;
                }
        } while (true);
}
int main()
{
        std::vector<int> myVec(10);
        myVec[0] = 2;
        myVec[1] = 4;
        myVec[2] = 6;
        myVec[3] = 8;
        myVec[4] = 10;
        myVec[5] = 12;
        myVec[6] = 14;
        myVec[7] = 16;
        myVec[8] = 18;
        myVec[9] = 20;
        int l = 3, r = 5;
        std::cout << "search(3, 5, 8) = " << search(myVec, 3, 5, 8) << std::endl;
        std::cout << "search(3, 5, 7) = " << search(myVec, 3, 5, 7) << std::endl;
        std::cout << "search(3, 5, 9) = " << search(myVec, 3, 5, 9) << std::endl;
        return 0;
}
    enter code here