【问题标题】:How can I return the right index with recursive binary search?如何使用递归二进制搜索返回正确的索引?
【发布时间】:2021-03-31 16:23:14
【问题描述】:

我尝试使用递归二进制搜索算法返回数组元素的正确索引,但它只返回所考虑部分的索引。
例如,如果列表由名称“Grant”、“Anthony”和“Samuel”组成,如果我搜索“Samuel”,算法将返回值 0。

short binarySearch(person key, person list[], short n)
{
    size_t mid;
    if(n == 0)
        return -1;
    mid = (n-1)/2;
    if(strcmp(key.name, list[mid].name) == 0 && strcmp(key.surname, list[mid].surname) == 0)
        return mid;
    
    else if(strcmp(key.name, list[mid].name) < 0)
        return binarySearch(key, list, mid);
    else
        return binarySearch(key, list+mid+1, n-mid-1);
}

更新:

我以这种方式解决了(感谢@mevets 和@selbie):

int binarySearch(person key, person *list, size_t n)
{
    int cmp = 0, result;
    size_t mid;
    if(n == 0)
        return -1;
    mid = (n - 1) / 2;
    cmp = strcmp(key.name, list[mid].name);
    if(cmp == 0)
    {
        cmp = strcmp(key.surname, list[mid].surname);
        if(cmp == 0)
            return mid;
    }
    if(cmp < 0)
        return binarySearch(key, list, mid);
    result = binarySearch(key, list+mid+1, n-mid-1);
    if(result == -1)
        return -1;
    return 1 + mid + result;
}

【问题讨论】:

  • 程序中的一个小错误 - 如果列表中的两个项目具有相同的 name 属性值,但不同的 surname 值,您可能会递归错误的子数组。考虑数组[{"bob", "anderson"}, {"bob", "jones"}, {"bob, "zumuda"}]。然后搜索"bob anderson"
  • 这当然假设您的物品是按名字和姓氏排序的。如果项目是按姓氏排序的,仍然存在类似的错误。我将在下面更新我的答案以显示修复。

标签: c algorithm recursion


【解决方案1】:

不要调整listn(列表大小),而是传递列表的开始/结束索引。

另外,请注意,在处理名字相同但姓氏不同的用户时,您的程序有一个小错误

int binarySearch(const person* key, const person* list, int start, int end)
{
    // end is "1 past" the last valid index in list
    int cmp = 0;

    int mid = (start + end) / 2;

    if (start >= end)
    {
        return -1;  // list is empty or we've exceeded our bounds
    }

    // sorting on name, then surname as tiebreaker
    // if you need to sort on surname first, swap the two strcmp statements
    cmp = strcmp(key->name, list[mid].name);
    if (cmp == 0)
    {
        cmp = strcmp(key->surname, list[mid].surname);
        if (cmp == 0)
        {
            return mid;
        }
    }

    if (cmp < 0)
    {
        // recurse into the left side of the array
        return binarySearch(key, list, start, mid);
    }
    
    // recurse into the right side of the array
    return binarySearch(key, list, mid + 1, end);
}

然后作为现有函数签名的垫片:

short binarySearch(person key, person list[], short n)
{
    return binarySearch(&key, list, 0, n);
}

另外,为了提高效率,您应该通过指针而不是值传递keylist 已作为指针传递。

【讨论】:

  • 非常感谢!那么只有数组大小没有办法做到这一点?
  • 数组在 C 中没有大小。当传递给函数时,它们只是指针。
  • 是的,我知道,我的意思是数组元素的数量。顺便谢谢你的回答!
  • 您可以在下面获取 mevets 的答案,然后在进行 mid+1 调整之前检查 -1 作为返回码。我还为您提供了一些其他错误修复。
  • 没错。 result = binarySearch(...); if (result == -1) return -1; return mid+1+result;
【解决方案2】:

改变你的最后一个:

return binarySearch(key, list+mid+1, n-mid-1);

到:

return mid + 1 + binarySearch(key, list+mid+1, n-mid-1);

【讨论】:

  • 又好又甜。
  • 为什么如果我输入一个未列出的字符串有时它不返回-1?例如,如果我输入“姓名:j 姓:K”,它会返回与字符串“John”和“Kennedy”匹配的索引。
  • 对,不是一个很好的解决方案。如果找不到元素,搜索例程通常会返回插入点,所以i = binarySearch(key, list, n); if (i &gt; 0 &amp;&amp; strcmp(key.name, list[i].name) { i = -1; }
  • 或者看看下面的@selbie重写它
  • strcmp 的结果应该是什么? strcmp != 0?
猜你喜欢
  • 1970-01-01
  • 2019-01-19
  • 2016-11-14
  • 1970-01-01
  • 1970-01-01
  • 2020-06-26
  • 2015-02-10
  • 1970-01-01
  • 2020-03-04
相关资源
最近更新 更多