使用二叉搜索搜索向量的上限

Searching vector's upper bound using binary search

本文关键字:搜索 向量      更新时间:2023-10-16

给定一个输入(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;
   }
}

我的算法没有返回正确的上界。有人能帮我弄清楚我哪里错了吗。

我只想使用"指针"遍历这个向量。我不想使用内置函数来寻找上界,因为我想了解我的算法哪里出了问题。

您没有仔细考虑请求值大于向量中任何值的情况,忽略这种情况也会导致其他情况出错。

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

  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
}

代码真的很琐碎。边界案例值得思考,但我认为它们都是可行的。如果向量<值1时,此代码返回经过矢量末尾的第一个位置。这是一个设计选择(不是对错)。如果你不喜欢这个选择,那么改变应该很容易。

在任何二进制搜索中,您都需要注意它总是收敛的,永远不会陷入在r==l+1时不更改lr的循环中。这是二进制搜索中一个常见的缺陷,我在代码中评论了我认为它不会发生的原因。

然后,您需要精确定义lr的点,以查看边界情况是否安全。l只通过元素<value1,所以我们仍然确信它不会通过可能是==value1的第一个元素。r备份到不是<value1的项目,因此它可能跨项目==value1进行备份,因此在多个项目匹配value1的边界情况下,我们似乎找到了第一个。这是一个偶然的"设计选择",你可能愿意也可能不愿意改变。但除此之外,我们至少看到r从未备份到项目<value1

看起来您正试图使用pointerUpperBound作为输出参数,但您按值传递了

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

传递引用。