【问题标题】:Binary Search in C returns FALSE all the timeC中的二进制搜索一直返回FALSE
【发布时间】:2021-11-14 21:59:29
【问题描述】:

所以我根据维基百科伪代码用 C 语言编写了一个二进制搜索程序,但即使在处理只有一个元素的数组时它也会一直返回 false。我不知道哪里出了问题。任何帮助表示赞赏!顺便说一句,这是一个编码挑战,所以我没有自己编写测试套件。

编辑:功能正在测试如下:

int arr[] = {6};
size_t length = sizeof(arr)/sizeof(*arr);
TEST_ASSER((&arr[0] == binary_search(6, arr, length));


int *binary_search(int value, const int *arr, size_t length) {
    int L = 0;
    int R = length - 1;
    static int m;
    while(L <= R) {
        m = floor((L + R) / 2);
        if(arr[m] < value) {
            L = m + 1;
        } else if(arr[m] > value) {
            R = m - 1;
        } else { return (&m); }
    }
    return 0;
} 

编辑:因此,在我从原始函数中删除了 const 项后,它与以下代码一起使用。感谢大家的帮助!

int *binary_search(int value, int *arr, size_t length) {
    int L = 0;
    int R = length - 1;
    static int m;
    while(L <= R) {
        m = (L + R) / 2; // no floor needed
        if(arr[m] < value) {
            L = m + 1;
        } else if(arr[m] > value) {
            R = m - 1;
        } else {
            return &arr[m];
        }
    }
    return 0; // not found
}

【问题讨论】:

  • return (&amp;m) 真的没有意义。为什么要返回指向索引的指针,而不是索引本身?此外,floor((L + R) / 2) 也没有多大意义,因为所有涉及的值都是整数值,结果将是截断的整数值。
  • 至于您的问题,您尝试搜索的数据是什么?你如何调用你的函数?你如何检查它的结果?请尝试创建一个minimal reproducible example 向我们展示,最好使用您传递给函数的硬编码数组。
  • 欢迎来到 SO。请提供MCVE,说明您如何调用函数以及输入的数据。
  • 我认为您应该将此作为学习如何调试代码的最佳时机。更具体地说,如何使用 debugger 在监控变量及其值的同时逐条执行代码。
  • 回到我的第一条评论,想想你实际上从函数中返回了什么。然后想想你期望它返回什么,因为这不是函数返回的。

标签: arrays c algorithm binary-search function-definition


【解决方案1】:

数组的长度被声明为具有size_t的类型

int *binary_search(int value, const int *arr, size_t length) {

因此,在函数中,变量LRm 也应声明为具有size_t 类型。

也使用函数 floor

m = floor((L + R) / 2);

绝对没有意义,因为表达式(L + R) / 2 具有整数类型int

将变量m 声明为静态也没有多大意义。

函数应该返回找到的元素在数组中的位置,或者如果没有找到这样的元素,则返回数组的大小。

在这种情况下

TEST_ASSER((&arr[0] == binary_search(6, arr, length));

将数组arr的第一个元素的地址与静态局部变量m的地址进行比较。很明显,这些对象占用不同程度的内存。因此,条件将始终评估为逻辑假。

函数可以声明一个定义,例如下面的演示程序所示。

#include <stdio.h>

size_t binary_search( const int a[], size_t n, int value )
{
    size_t low = 0, high = n;
    
    while ( low < high )
    {
        size_t middle = low + ( high - low ) / 2;
        
        if ( value < a[middle] )
        {
            high = middle;
        }
        else if ( a[middle] < value )
        {
            low = middle + 1;
        }
        else
        {
            return middle;
        }
    }
    
    return n;
}

int main(void) 
{
    int a[] = { 6 };
    const size_t N = sizeof( a ) / sizeof( *a );
    
    int value = 6;
    
    size_t pos = binary_search( a, N, value );
    
    if ( pos != N )
    {
        printf( "The value %d is found at position %zu\n", value, pos );
    }
    else
    {
        printf( "The value %d is not found.\n", value );
    }
    
    value = 5;
    
    pos = binary_search( a, N, value );
    
    if ( pos != N )
    {
        printf( "The value %d is found at position %zu\n", value, pos );
    }
    else
    {
        printf( "The value %d is not found.\n", value );
    }
    
    value = 7;
    
    pos = binary_search( a, N, value );
    
    if ( pos != N )
    {
        printf( "The value %d is found at position %zu\n", value, pos );
    }
    else
    {
        printf( "The value %d is not found.\n", value );
    }
    
    return 0;
}

程序输出是

The value 6 is found at position 0
The value 5 is not found.
The value 7 is not found

另一种方法是定义函数,使其返回指向数组中找到的元素的指针,如果找不到这样的元素,则返回 NULL

这里还有一个演示程序。

#include <stdio.h>

int * binary_search( const int a[], size_t n, int value )
{
    size_t low = 0, high = n;
    
    while ( low < high )
    {
        size_t middle = low + ( high - low ) / 2;
        
        if ( value < a[middle] )
        {
            high = middle;
        }
        else if ( a[middle] < value )
        {
            low = middle + 1;
        }
        else
        {
            return ( int * )( a + middle );
        }
    }
    
    return NULL;
}

int main(void) 
{
    int a[] = { 6 };
    const size_t N = sizeof( a ) / sizeof( *a );
    
    int value = 6;
    
    int *pos = binary_search( a, N, value );
    
    if ( pos != NULL )
    {
        printf( "The value %d is found at position %tu\n", value, pos - a );
    }
    else
    {
        printf( "The value %d is not found.\n", value );
    }
    
    value = 5;
    
    pos = binary_search( a, N, value );
    
    if ( pos != NULL )
    {
        printf( "The value %d is found at position %tu\n", value, pos - a );
    }
    else
    {
        printf( "The value %d is not found.\n", value );
    }
    
    value = 7;
    
    pos = binary_search( a, N, value );
    
    if ( pos != NULL )
    {
        printf( "The value %d is found at position %tu\n", value, pos - a );
    }
    else
    {
        printf( "The value %d is not found.\n", value );
    }
    
    return 0;
}

程序输出同上图。

The value 6 is found at position 0
The value 5 is not found.
The value 7 is not found.

【讨论】:

    【解决方案2】:

    二分查找的逻辑应该是这样的

    int *binary_search(int value, const int *arr, size_t length) {
            int L = 0;
            int R = length - 1;
            static int m;
            while(L <= R) {
              m = floor((L + R) / 2);
              if(arr[m]==value)
              {
              // element found
              }
               else if(arr[m] < value) {
                    L = m + 1;
                } else if(arr[m] > value) {
                    R = m - 1;
                } 
            }
            return 0;
        } 
    

    如果执行了while循环并且没有进入if(arr[m]==value)内部意味着元素不在列表中

    【讨论】:

    • 提问者已经有了识别相等性的逻辑。您的代码没有添加任何内容。
    【解决方案3】:

    您的return 语句返回一个局部变量的地址:&amp;m。这绝对是错误的,因为在函数返回后不再分配此内存,而且它肯定不是您拥有的驱动程序代码中预期的地址。

    快速解决方法是return &amp;arr[m],但是就像在cmets中所说的那样,返回数组元素的地址很奇怪。

    只需返回索引,并相应地调整函数返回类型,以及驱动代码:

    #include <stdio.h>
    
    
    int binary_search(int value, const int *arr, size_t length) {
        int L = 0;
        int R = length - 1;
        static int m;
        while(L <= R) {
            m = (L + R) / 2; // no floor needed
            if(arr[m] < value) {
                L = m + 1;
            } else if(arr[m] > value) {
                R = m - 1;
            } else {
                return m;
            }
        }
        return -1; // not found
    }
    
    int main(void) {
        printf("Hello World\n");
        int arr[] = {6, 9, 13, 25};
        size_t length = sizeof(arr)/sizeof(*arr);
        if (1 == binary_search(6, arr, length)) {
            printf("ok!\n");
        }
    
        return 0;
    }
    

    【讨论】:

    • 问题似乎是函数返回一个整数指针。编译器给出此错误:从返回类型为 'int *' 的函数中返回 'int' 使指针从整数而不进行强制转换...
    猜你喜欢
    • 1970-01-01
    • 2015-02-10
    • 2020-04-02
    • 2016-05-03
    • 1970-01-01
    • 2020-11-24
    • 1970-01-01
    • 2019-05-21
    • 2022-01-22
    相关资源
    最近更新 更多