简体   繁体   中英

Searching vector's upper bound using binary search

Given an input(value1) I need to find its upper bound in a vector("vec"). Instead of returning the upper bound value, I need to return pointer to this upper bound value.

vector<int> vec;
vec.push_back(5); vec.push_back(7); vec.push_back(15); 

If my input value1="13", then my function upperBound() should return pointer to element 15.

upperBound() function returns "pointerUpperBound" -- which is a pointer to the upper bound of value1.

Upper bound in my case means a value which is greater than or equal to the input value (value1). It is the smallest number that is greater than the input

 //**GOAL OF ALGORITHM: Given "value1" it needs to find value1's upper bound  in vector "vec". Instead of return the upper bound element, I need to return pointer to upper bound element**
bool upperBound(int* &pointerUpperBound,int value1, vector<int> vec)
    // Perform a binary search
{
   unsigned left=0,right=(vec.size()-1);
   int* l=&vec[0];
   int* r=(l+vec.size()-1); //l will be start of pageInfo vector and r will be end of page info vector
   if(vec.size()==1) //vec has just one element in it.
   {
       pointerUpperBound=l;
       return true;

   }   
   while (left!=right) {
      int* pointerUpperBound=l+((r-l)/2); 
      unsigned middle=left+((right-left)/2);
      if(value> (*pointerUpperBound)) {     
         l=pointerUpperBound+1;
         left=middle+1;
      } else if (!middle) { //reached the upper bound, it is "pointerUpperBound" which is also returned.
         break;
      } else {
         int* prev=pointerToUpperBound;
         prev--;
         if(value1 > (*prev)) {
             break;
         } else{
             right=middle;
             r=pointerToUpperBound;
         }
      }
   }
   // Unsuccessful search?
   if (left==right) {
       return false;
   }
}

My algorithm does not return correct upper bounds. Can someone please help me figure out as to where am I going wrong.

I want to traverse this vector using "pointers" only. I dont want to use built-in functions for finding upper bound -- as I want to learn where my algorithm is going wrong.

Looks like you're trying to use pointerUpperBound as an output parameter, but you pass it by value .

The caller won't see the modifications you make to the the pointer.

Pass a reference.

You haven't thought through the case that the requested value is greater than anything in the vector, and by ignoring that case you got other cases wrong as well.

You haven't posted the real code you tested because:

  int* pointerUpperBound=l+((r-l)/2); 
  unsigned middle=left+((right-left)/2);
  if(value> (*pointerUpperBound)) {     
     l=m+1;

What is m ??

All that redundant work (pointer and unsigned copy in parallel) is just a source of confusion. Use one or the other.

Think about your code (after you made the above correction):

  if(value> (*pointerUpperBound)) {     
     l=pointerUpperBound+1;
     left=middle+1;
  }

If value > *r the above code could reach l=r+1; Is that what you intended for that case? If not, what did you intend?

What case did you think you were covering with the final?

   // Unsuccessful search?
   if (left==right) {
       return false;
   }

Think about the situation in which r==l+2 and the answer you want is r . You try location l+1 and it is too small, so you set l=l+1+1; and never try that location because it is r but you simply end the loop and return false . You snatch defeat from the jaws of victory.


bool upperBound(int* &pointerUpperBound,int value1, vector<int> vec)
    // Perform a binary search
{
   int* l=&vec[0];  // Pointer to lowest that might be == value1
   int* r=l+vec.size(); //Pointer PAST last value that might be < value1

   while ( l < r ) {
      int* m=l+((r-l)/2); // Notice m<r, m>=l
      if( value1 > *m ) {     
         l=m+1;  // l always increases here
      } else {
         r=m;  // m always decreases here
      }
   }
   pointerUpperBound = l;  // first position >= value1
}

The code is really trivial. The boundary cases deserve thought, but I think they all work out. If every item in the vector < value1, this code returns the first position past the end of the vector. That is a design choice (not right or wrong). If you don't like that choice, it should be easy to change.

In any binary search, you need care that it always converges, never gets stuck in a loop not changing l or r when r==l+1 . That is a common enough flaw in binary searches that I commented in the code the reasons I think it doesn't happen.

Then you need a precise definition of where l and r point in order to see whether boundary cases are safe. l passes only elements <value1 so we remain sure it doesn't pass the first element that might ==value1 . r backs up to items not <value1 so it might back up across items ==value1 so in the boundary case of multiple items matching value1 we seem to find the first. That is an accidental "design choice" you might or might not prefer to change. But otherwise, we at least see r never backs up to an item <value1

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM