严格执行C中的下限

时间:2016-09-16 18:40:04

标签: c arrays sorting binary-search

我已经提出了这个解决方案来在排序数组中严格实现下限:

long lowerBound(long key, long size, long *a){
    long low = 0, high = size, mid;
    if(a[low] >= key){
        return -1;
    }
    while(low < high){
        mid = (low+high)/2;
        if(a[mid] >= key){
            high = mid - 1;
        } else{
            low = mid;
        }
    }
    return low;
}

但这似乎不起作用。它在一些测试用例中失败了。例如:

A [7] = {0,1,1,3,5,5,10}

key = 4

进入无限循环。

以下是测试运行:

第一次迭代后: low = 3,high = 7,mid = 3

第二次迭代后: low = 3,high = 4,mid = 5

第三次迭代后: 低= 3,高= 4,中= 3。 然后它就卡住了。

任何人都可以指出我正确的方向。在此先感谢!!

4 个答案:

答案 0 :(得分:2)

它会被卡住&#34;因为当您的low等于high - 1时,mid变为low(low+low+1)/2 == low,则a[mid] >= keyfalsemid }再次设置为low。如果low,您需要将mid + 1设置为a[mid] < key,否则将high设置为mid。然后你会发现第一次出现key,或者,如果没有元素,等于key,第一次出现的元素大于key,如果所有元素都小于key,你会得到高的初始值

UPD:而且,由于它的二进制搜索,您始终获取low == high - 1。下次记住这一点!

UPD2:还有一件事!最好使用mid = low+((high-low)/2),因为这样可以防止出现一些溢出错误。

答案 1 :(得分:0)

举个例子:

low = 3
high = 4

那么你的代码会做什么?

while(low < high){         // True as 3 is less than 4
    mid = (low+high)/2;    // (3+4)/2 --> mid = 3
    if(a[mid] >= key){     // a[3] is 3. And 3 isn't greater or equal 4 so this is false
        high = mid - 1;
    } else{                // So you take the else part

        low = mid;         // low is assigned 3. So you are back
                           // where you started and have an endless loop
    }

您需要确保lowhigh的分配不只是分配他们已有的值。

例如:

else {
    if (low == mid) return low;
    low = mid;
}

答案 2 :(得分:0)

如果数组的每个元素都是唯一的,您可以使用以下内容:

long binsearch(long *a, long size, long key) {
    long lo = 0;
    long hi = size-1;

    if (hi == -1)
       return -1;

    while (1) {
       long mid = ( lo + hi ) / 2;
       if (a[mid] == key)
          return mid;

       if (a[mid] < key) {
          hi = mid - 1;
          if (lo > hi)
             return ~mid;
       } else {
          lo = mid + 1;
          if (lo > hi)
             return ~lo;
       }
    }
}

但你的阵列可能有重复,你想找到第一个,所以我们需要调整被认为匹配的东西。

long binsearch_first(long *a, long size, long key) {
    long lo = 0;
    long hi = size-1;

    if (hi == -1)
       return -1;

    while (1) {
       long mid = ( lo + hi ) / 2;
       if (a[mid] == key && ( mid == 0 || a[mid-1] != key ))
          return mid;

       if (a[mid] <= key) {
          hi = mid - 1;
          if (lo > hi)
             return ~mid;
       } else {
          lo = mid + 1;
          if (lo > hi)
             return ~lo;
       }
    }
}

您可能已经注意到了特殊的回报值。如果不是key,它的优势在于返回key。这会告诉您如果要将其添加到数组中,请插入long i = binsearch_first(a, a_size, key); if (i >= 0) { printf("The first %ld was found at index %ld.\n", $key, i); } else { printf("%ld wasn't found. It would have been found at index %ld.", $key, ~i); } 的位置。

FileName1
FileName2
FileName5
FileName6

答案 3 :(得分:-1)

你从high = size开始,所以上限超出了范围,应该保持这种状态,也就是说,它永远不是解决方案。

因此会出现两个错误:结束条件以及新high值的设置。

结束条件应为

while (high - low > 1)

之后解决方案将为low。并且新high值的设置应为

if(a[mid] > key){               // change from >=
    high = mid;                 // mid is not valid
}