使用二进制搜索搜索向量的上限

时间:2015-12-26 13:07:25

标签: c++ algorithm

给定输入(value1)我需要在向量(“vec”)中找到它的上界。我不需要返回上限值,而是返回指向此上限值的指针。

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

如果我的输入值1 =“13”,那么我的函数upperBound()应该返回指向元素15的指针。

upperBound()函数返回“pointerUpperBound” - 这是指向value1上限的指针。

在我的情况下,上限是指大于或等于输入值(value1)的值。它是最小的数字,大于输入

 //**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;
   }
}

我的算法没有返回正确的上限。有人可以帮我弄清楚我哪里出错了。

我想仅使用“指针”来遍历此向量。我不想使用内置函数来查找上限 - 因为我想知道我的算法出错了。

2 个答案:

答案 0 :(得分:2)

您似乎尝试将pointerUpperBound用作输出参数,但是您将按值传递

调用者不会看到您对指针所做的修改。

传递参考资料。

答案 1 :(得分:2)

您还没有想过所请求的值大于向量中的任何值,并且通过忽略该情况,您也会错误地处理其他情况。

您还没有发布您测试的真实代码,因为:

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

什么是m ??

所有冗余工作(指针和未签名的副本并行)只是一个混乱的来源。使用其中一个。

考虑一下你的代码(完成上述修正后):

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

如果value > *r以上代码可以达到l=r+1;那么您的意图是针对该情况吗?如果没有,你打算做什么?

你认为你在决赛中涉及什么案例?

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

考虑r==l+2和您想要的答案是r的情况。您尝试使用位置l+1并且它太小,因此您设置l=l+1+1;并且从不尝试该位置,因为它是r,但您只是结束循环并返回false。你从胜利的下颚中抢夺失败。

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
}

代码非常简单。边界情况值得思考,但我认为它们都有效。如果向量中的每个项目&lt; value1,此代码返回向量末尾的第一个位置。这是一个设计选择(不对或错)。如果你不喜欢这个选择,那么应该很容易改变。

在任何二进制搜索中,您需要注意它始终收敛,永远不会陷入不在lrr==l+1更改的循环中。这是二进制搜索中常见的漏洞,我在代码中评论了我认为它没有发生的原因。

然后,您需要精确定义lr指向的位置,以便查看边界情况是否安全。 l仅传递元素<value1,因此我们仍然确定它不会传递可能==value1的第一个元素。 r备份到不是<value1的项目,因此它可能会在项目==value1之间进行备份,因此在符合value1的多个项目的边界情况下,我们似乎找到了第一个项目。这是一个偶然的设计选择&#34;你可能会或不愿意改变。但除此之外,我们至少看到r永远不会备份到项目<value1