【问题标题】:Recursive binary search in sorted array c++排序数组c ++中的递归二进制搜索
【发布时间】:2016-01-07 19:55:40
【问题描述】:

我必须编写一个递归函数来搜索已排序的数组。

#include <iostream>
using namespace std;

int find(int value, int* folge, int max) {

}


int main() {
    int const n = 7;
    int wert1 = 4, wert2 = 13, wert3 = 2, wert4 = 25;
    int folge[n] = {3,4,9,13,13,17,22};
    wert1 = find(wert1, folge, n);
}

这是提供给我们的部分代码,我们必须完成它。
如果您有 4 个可用变量,我知道该怎么做。 (最小值和最大值) 但是我只有三个,有没有办法编辑给下一个函数的数组的起点?

【问题讨论】:

  • 一个数组名在普通使用中衰减为一个指针。所以看起来你是通过名称传递一个数组,你实际上只是传递一个int*。您可以通过简单地向其添加偏移量来递归地传递修改后的int*find(value, folge+m, max-m)
  • @SergeyA Wert 是我们要在数组中找到的数字
  • find 在找到您想要的项目时应该返回什么?找不到时应该返回什么?
  • 非常好的问题,但我建议您在发布问题之前将变量名称翻译成英文,这样我们的工作会轻松很多。

标签: c++ arrays algorithm recursion binary-search


【解决方案1】:

假设您有四参数版本:

find(value, array, min, max);

三参数版本可以调用:

find(value, array + min, max);

请注意,数组的第 max'th 元素实际上是 array + minmax-minth 元素,因此根据您的实现,您可能需要调用

find(value, array + min, max - min);

【讨论】:

  • 如果最后一个参数是计数,是的。如果是索引,则需要在基指针变化时进行调整。
  • @BenVoigt 在这种情况下,计数和索引是一回事,无论哪种方式都需要调整。在基础不变的情况下也需要进行调整。无论哪种方式,计数总是减少,在这种三参数形式的搜索中,计数总是一个索引。
【解决方案2】:

函数可以这样写

#include <iostream>

int find( int value, int* folge, int max ) 
{
    if ( max == 0 ) return -1;

    int middle = max / 2;

    if ( folge[middle] == value ) return middle;

    bool lower = value < folge[middle];
    int n = lower ? find( value, folge, middle ) 
                  : find( value, folge + middle + 1, max - middle - 1 );

    return n != -1 && !lower ? n + middle + 1: n; 
}

int main()
{
    int const n = 7;
    int wert1 = 4, wert2 = 13, wert3 = 2, wert4 = 25;
    int folge[n] = {3,4,9,13,13,17,22};

    std::cout << wert1 << " = " << find(wert1, folge, n) << std::endl;
    std::cout << wert2 << " = " << find(wert2, folge, n) << std::endl;
    std::cout << wert3 << " = " << find(wert3, folge, n) << std::endl;
    std::cout << wert4 << " = " << find(wert4, folge, n) << std::endl;

    return 0;
}

程序输出是

4 = 1
13 = 3
2 = -1
25 = -1

或者另外一个测试程序

#include <iostream>

int find( int value, int* folge, int max ) 
{
    if ( max == 0 ) return -1;

    int middle = max / 2;

    if ( folge[middle] == value ) return middle;

    bool lower = value < folge[middle];
    int n = lower ? find( value, folge, middle ) 
                                  : find( value, folge + middle + 1, max - middle - 1 );

    return n != -1 && !lower ? n + middle + 1: n; 
}

int main()
{
    int const n = 7;
    int folge[n] = {3,4,9,13,13,17,22};

    for ( int x : { 2, 3, 4, 9, 13, 17, 22, 25 } )
    {
        std::cout << x << " -> " << find( x , folge, n ) << std::endl;  
    }        

    return 0;
}

它的输出是

2 -> -1
3 -> 0
4 -> 1
9 -> 2
13 -> 3
17 -> 5
22 -> 6
25 -> -1

【讨论】:

    【解决方案3】:
    find( &folge[1],...) // ignore first element
    

    第n个元素的地址是一个大小为Size-n的数组

    【讨论】:

      【解决方案4】:

      如果folge 指向第一个元素,那么folge+1 将指向第二个元素。

      int find(int value, int* folge, int max)
      {
          int m = max/2;
          if (0 == max)
          {
              return -1;
          }
      
          if (value == folge[m])
          {
              return value;
          }
          else if (value < folge[m])
          {
              return find(value, folge, m);
          } else
          {
              return find(value, folge + m + 1, max - m - 1);
          }
      }
      

      【讨论】:

      • 你的讨论/调整folge的例子是正确的,但是你的二分搜索逻辑有一些错误。
      【解决方案5】:

      可以改变int指针folge的值

      int find(int value, int* folge, int max) {
         if (max == 0) {
              return -1;
         }
      
         int mid=max/2;
      
         if (value == folge[mid])
         {
              return mid;
         }
      
         int base=0;
      
         if (value < folge[mid])
         {
             max=mid-1;
         }
         else
         {
             max-=(mid+1);
             base=mid+1;
         }
      
         int ret=find(value,folge+base,max);
      
         if (ret == -1)
         {
             return -1;
         }
      
         return ret+base;
      }
      

      【讨论】:

      • 最后一行将编译为逗号运算符,可能不是您想要的。此外,传统的二分搜索函数会返回找到该项目的索引,而不是它的值(您已经知道)。当然,当max == 1 时,您会遇到不终止的问题,因为max - max/2 不会减少。
      • @BenVoigt 切换到基于索引的回报并清理
      最近更新 更多