27

I need a binary search function.

I couldn't find any function in the standard library that will return the index of the found item, and if it wasn't found, will return the bitwise complement of the index of the next element that is larger than the item I looked for.

What is the function I am looking for?

Edit: I need to insert an item to a sorted vector and to keep it sorted. That's why I need to bitwise complement index.

liran63
  • 1,300
  • 2
  • 15
  • 17
  • 2
    I think `std::lower_bound` will give you the correct insertion point in order to keep your `std::vector` sorted. In fact I have written a `map` implementation using `std::vector` and `std::lower_bound`. – Galik Dec 11 '14 at 20:00
  • Yes you are right. I'll use it. sry :) – liran63 Dec 11 '14 at 20:02

9 Answers9

17

I'm quite certain the standard library doesn't include anything to do precisely what you're asking for.

To get what you want, you'll probably want to start from std::lower_bound or std::upper_bound, and convert the iterator it returns into an index, then complement the index if the value wasn't found.

  • lower_bound will find the position of the first item with that value, or the position of the first item greater than the specified value, if the value you specified is not present (or .end() if no larger item is present).
  • upper_bound will find the position just past the last item with the specified value (and, again, .end() if no larger value is present).

It sounds like you want your collection to contain only unique values (i.e., a value occurs at most once). If so, you probably want to use std::lower_bound. Then subtract the result from yourVector.begin() to get an index. Finally, compare what it points at to the specified value, and complement the index if they're not equal.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • "upper_bound will find the position of the last item with that value (again, if any)" is not correct; instead, it returns the first element strictly greater than the provided value or the end iterator if not found. – Ashutosh Aswal Aug 27 '23 at 04:42
  • @AshutoshAswal: Oops, quite right. Thank you. – Jerry Coffin Aug 27 '23 at 15:59
13

There is no simple STL method which returns index against a sorted vector as far as I know, however you can use sample function below:

/**
 * @param v - sorted vector instance
 * @param data - value to search
 * @return 0-based index if data found, -1 otherwise
*/
int binary_search_find_index(std::vector<int> v, int data) {
    auto it = std::lower_bound(v.begin(), v.end(), data);
    if (it == v.end() || *it != data) {
        return -1;
    } else {
        std::size_t index = std::distance(v.begin(), it);
        return index;
    }   
}
Jonathan L
  • 9,552
  • 4
  • 49
  • 38
4

This code should work fine

auto itr = lower_bound(v.begin(), v.end(), key) ;
index = distance(v.begin(), itr);

More about std::lower_bound() - https://www.geeksforgeeks.org/stdlower_bound-in-c/

DekuDesu
  • 2,224
  • 1
  • 5
  • 19
UNREAL
  • 430
  • 5
  • 11
1

Clearly, this "will return the bitwise complement" is a big deal for you and I do not understand what you mean. That said, lookup std::upper_bound and see if it does what you want.

Happy Green Kid Naps
  • 1,611
  • 11
  • 18
0

using STL we can find the index

vector<int> vec{1,2,3,4,5,6,7,8,9} ;
vector<int> :: iterator index;
index=lower_bound(vec.begin(),vec.end(),search_data);
return (index-vec.begin());
  • 2
    This is essentially the same as @Jonathan's answer, but lacks handling the "not found" case and is less readable. Also, `return` is not a function. So, no need to put the return value in parentheses. – Adrian W Jul 01 '18 at 16:52
0
int bin_search (ForwardIterator first, ForwardIterator last, const T& val)
{
  ForwardIterator low;
  low = std::lower_bound(first,last,val);
  if(low!=last && !(val<*low)){
    return (low - first + 1);
  }else{
    return 0;
  }
}
Sarvpriy
  • 21
  • 4
  • 5
    Hi there! Can you give us more information on how your code works, and why it will solve the question? – hat Mar 02 '19 at 15:05
0
int a = 0, b = n-1;
while (a <= b) {
    int k = (a+b)/2;
    if (array[k] == x) 
    {
        // x found at index k
    }
    if (array[k] < x) a = k+1;
    else b = k-1;
}
Pang
  • 9,564
  • 146
  • 81
  • 122
Yash
  • 1
  • 1
0

Using Jonathan's answer, a one line function, for the case where we want to know at which index the value is or should have been if it does not exist:

int searchInsert(vector<int>& nums, int target) {
    return lower_bound(nums.begin(), nums.end(), target) - nums.begin();
}
Antonin GAVREL
  • 9,682
  • 8
  • 54
  • 81
0

I was working on a similar problem where I needed to insert an element in a vector while keeping it sorted. The solution I came up with is:

The function(modified binary search) returns the position where the value should be inserted.

int Position(vector<int> arr, size_t size, int val)//void for commented part
{
    int start=0, middle, end=size-1;
    while(arr[start] <= arr[end])
    {
        middle = (int)((start+end+1)/2);
        if (arr[middle] < val)
        {
            start = middle+1;
        }
        else if (arr[middle] > val)
        {
            end = middle-1;
        }
        else//arr[middle]=val;
        {
            return middle;
        }
    }
    mid = (int)((start+end+1)/2);
    //arr.insert(arr.begin()+mid, val); Can I do it here? got error trying to do it.
    return mid;
}
int main()
{
    vector<int> x; cin>> val;
    mid = Position(x, x.size(), val);
    x.insert(x.begin()+mid, val);
}
Miraz
  • 343
  • 3
  • 15