如果声明无法识别真实条件?

时间:2016-07-19 21:31:53

标签: c binary-search

我在使用这种二进制搜索算法时遇到了麻烦。以下是变量的解释。

value:在数组中搜索的数字

values []:正在搜索的数组

n:数组中元素的数量

高:被搜索数组部分的最高元素(按零索引位置)

low:最低元素(按零索引位置)被搜索数组的部分

我的问题不在于递归。被搜索的数组部分以"值"为中心。和以下确定的条件正在得到满足。问题是我的if语句似乎并没有意识到它们是。我知道条件正在满足,因为当我打印出每个递归的值[high],值[middle]和值[low]时,它表明它们是。

int search(int value, int values[], int n, int high, int low)
 {   
   if (n <= 0)
   {
    return 1;
   }

   int middle = (high + low) / 2;

     ///condition #1
   if (value == values[middle])
   {
     return 0;
   }

   //conditions #2 and #3 (account for the maxes and mins of the array because the operation to find middle truncates)
  else if ( values[middle]==values[low] || values[middle]==values[high])
    {
     return 0;
    }

  else if (value > values[middle])
   {
        low = middle;
        search(value, values, n, high, low);
   }

  else if (value < values[middle])
   {
      high = middle;
      search(value, values, n, high, low);
   }

    return 2;
   } 

这里有什么问题?

2 个答案:

答案 0 :(得分:3)

仔细看看这段代码:

else if (value > values[middle])
{
     low = middle;
     search(value, values, n, high, low);
}

else if (value < values[middle])
{
   high = middle;
   search(value, values, n, high, low);
}

请注意,在这些情况下,您会递归调用search函数,但是您不会对返回值执行任何操作。这意味着,search返回的任何值都将被丢弃,代码将继续执行,最终返回2

要解决此问题,请添加以下return语句:

else if (value > values[middle])
{
     low = middle;
     return search(value, values, n, high, low);
}

else if (value < values[middle])
{
   high = middle;
   return search(value, values, n, high, low);
}

一般来说,如果您怀疑if声明条件没有触发,那么使用调试器慢慢地逐步处理事情是值得的。这样做可能会让您注意到您(1)正确地递归调用函数,但(2)返回并丢弃返回的值。

此处的代码可能存在其他问题,但这肯定是您需要解决的问题。

答案 1 :(得分:2)

Quoth cb3k

  

这似乎使其有效......其他问题可能是什么?

这里的代码是fix诊断出的最小(必要但不充分)templatetypedef和测试工具。

#include <stdio.h>

static
int search(int value, int values[], int n, int high, int low)
{
    if (n <= 0)
    {
        return 1;
    }

    int middle = (high + low) / 2;

    ///condition #1
    if (value == values[middle])
    {
        return 0;
    }

    // conditions #2 and #3 (account for the maxes and mins of the array because the operation to find middle truncates)
    else if (values[middle] == values[low] || values[middle] == values[high])
    {
        return 0;
    }

    else if (value > values[middle])
    {
        low = middle;
        return search(value, values, n, high, low);
    }

    else if (value < values[middle])
    {
        high = middle;
        return search(value, values, n, high, low);
    }

    return 2;
}

int main(void)
{
    int data[15];
    for (int i = 0; i < 15; i++)
        data[i] = 2 * i + 1;

    printf("Data:");
    for (int i = 0; i < 15; i++)
        printf("%3d", data[i]);
    putchar('\n');

    for (int i = -1; i < 2 * 15 + 3; i++)
        printf("Search for %2d - result %d\n", i, search(i, data, 15, 14, 0));
    return 0;
}

这是输出:

Data:  1  3  5  7  9 11 13 15 17 19 21 23 25 27 29
Search for -1 - result 0
Search for  0 - result 0
Search for  1 - result 0
Search for  2 - result 0
Search for  3 - result 0
Search for  4 - result 0
Search for  5 - result 0
Search for  6 - result 0
Search for  7 - result 0
Search for  8 - result 0
Search for  9 - result 0
Search for 10 - result 0
Search for 11 - result 0
Search for 12 - result 0
Search for 13 - result 0
Search for 14 - result 0
Search for 15 - result 0
Search for 16 - result 0
Search for 17 - result 0
Search for 18 - result 0
Search for 19 - result 0
Search for 20 - result 0
Search for 21 - result 0
Search for 22 - result 0
Search for 23 - result 0
Search for 24 - result 0
Search for 25 - result 0
Search for 26 - result 0
Search for 27 - result 0
Search for 28 - result 0
Search for 29 - result 0
Search for 30 - result 0
Search for 31 - result 0
Search for 32 - result 0

无论所寻找的值是否存在于数组中,它都返回0。这是不正确的行为。

你应该抽出时间去Jon Bentley学习Programming Pearls。它涵盖了以各种形式测试二进制搜索的基础知识 - 显示的测试工具是他所描述的变体。另请花点时间阅读 Extra, Extra - Read All About It: Nearly All Binary Searches and Mergesorts are Broken。也许你应该保证,随着时间的推移,许多其他人的二进制搜索错误。 (IIRC,二元搜索的第一个版本发布于20世纪50年代,但直到20世纪60年代早期才发布正确的版本 - 然后还有2006年的额外信息。)< / p>

当我在printf()之后的块中添加else if (values[middle] == values[low] || values[middle] == values[high])时,它会在每次应该失败的搜索上打印。请注意,界面使得很难发现发生了什么 - 它没有报告找到元素的位置,只是它是否被找到。您可以添加处理剩余问题所需的调试和代码更改。 (提示:该条件可能不是解决方案的一部分。但是,当您删除它时,代码会进入永久循环,因为您不会消除已知值不在您范围内的值递归检查。)

这似乎有效 - 请注意return 2;永远不会被执行(因为最终else if永远不会错误。

#include <stdio.h>

static
int search(int value, int values[], int n, int high, int low)
{
    //if (n <= 0)
    if (n <= 0 || high < low)
    {
        return 1;
    }

    int middle = (high + low) / 2;

    ///condition #1
    if (value == values[middle])
    {
        return 0;
    }

#if 0
    // conditions #2 and #3 (account for the maxes and mins of the array because the operation to find middle truncates)
    else if (values[middle] == values[low] || values[middle] == values[high])
    {
        //printf(" (#2 || #3) ");
        return 0;
    }
#endif

    else if (value > values[middle])
    {
        //low = middle;
        low = middle + 1;
        return search(value, values, n, high, low);
    }

    else if (value < values[middle])
    {
        //high = middle;
        high = middle - 1;
        return search(value, values, n, high, low);
    }

    return 2;
}

int main(void)
{
    int data[15];
    for (int i = 0; i < 15; i++)
        data[i] = 2 * i + 1;

    printf("Data:");
    for (int i = 0; i < 15; i++)
        printf("%3d", data[i]);
    putchar('\n');

    for (int i = -1; i < 2 * 15 + 3; i++)
        printf("Search for %2d - result %d\n", i, search(i, data, 15, 14, 0));
    return 0;
}

输出:

Data:  1  3  5  7  9 11 13 15 17 19 21 23 25 27 29
Search for -1 - result 1
Search for  0 - result 1
Search for  1 - result 0
Search for  2 - result 1
Search for  3 - result 0
Search for  4 - result 1
Search for  5 - result 0
Search for  6 - result 1
Search for  7 - result 0
Search for  8 - result 1
Search for  9 - result 0
Search for 10 - result 1
Search for 11 - result 0
Search for 12 - result 1
Search for 13 - result 0
Search for 14 - result 1
Search for 15 - result 0
Search for 16 - result 1
Search for 17 - result 0
Search for 18 - result 1
Search for 19 - result 0
Search for 20 - result 1
Search for 21 - result 0
Search for 22 - result 1
Search for 23 - result 0
Search for 24 - result 1
Search for 25 - result 0
Search for 26 - result 1
Search for 27 - result 0
Search for 28 - result 1
Search for 29 - result 0
Search for 30 - result 1
Search for 31 - result 1
Search for 32 - result 1