【问题标题】:C++ - Trouble Understanding a Divide and Conquer FunctionC++ - 无法理解分而治之的函数
【发布时间】:2018-05-23 22:18:33
【问题描述】:

我无法理解这个分而治之的函数如何比较数据元素:

int main()
{
  int arr[] = { -5, -10, -16, -3, -7 };
  int largest;

  largest = largest_element(arr, 0, sizeof(arr) / sizeof(int));
  cout << "Largest element in arr is " << largest << ".\n";

  return 0;
}
int largest_element(const int *a, int begin, int past_end)
{
  int result;
  int mid;
  int left_large;
  int right_large;

  assert(begin >= 0);
  assert(begin < past_end);

  if (past_end - begin == 1)
    result = a[begin];
  else {
    mid = (begin + past_end) / 2;
    left_large = largest_element(a, begin, mid);
    right_large = largest_element(a, mid, past_end);
    if (left_large >= right_large)
      result = left_large;
    else
      result = right_large;
  }

  //STOP! draw tree here when begin == 1, and past_end == 2.
  return result;
}

我知道数组被简单地分成更小的子数组,一旦达到基本情况,它将返回 a[begin]。但是,根据我的图表,如果我们有一个包含两个元素的数组,它只是返回第一个值,我不明白如何真正比较这些值。例如,如果数组中最右边的元素没有其他可比较的元素,如何比较它?

Here is my diagram.我没有其他图表可与之比较。

【问题讨论】:

  • past_end - begin == 1 在只剩下一个元素而不是两个元素时为真。因此,单个元素之间的比较发生在倒数第二级的if(left_large &gt;= right_large) 行中。
  • 当数组中有两个值时,请使用调试器单步执行此程序,并亲自查看。这就是调试器的用途。
  • 第一次比较只发生在right_large = largest_element(a, 1, 2);之后。但我猜指令说在那之前停止?目前尚不清楚评分者在寻找什么,我们可能必须在您的课堂上才能确切知道这些图表是如何教给您的。
  • 如果你有一个包含两个元素的数组({5, 7}),它会将它分成两个子问题;一种是返回5,另一种是返回7。函数返回这两个中的最大值。

标签: c++ arrays recursion divide


【解决方案1】:

我不明白这些值是如何真正比较的,如果我们有 一个包含两个元素的数组,它只返回第一个值。

我无法重现该发现。当 arr 只有 2 个元素时,该函数仍然返回两者中较大的一个。

您的调试器是评估您的代码并找出您的误解的合适方法。

但是,添加诊断并允许代码报告其进度可能会很有趣。这是一种技术:

#include <iostream>
#include <iomanip>
#include <sstream>
#include <string>
#include <cassert>


class T548_t
{
   int depth;

public:

   T548_t() = default;
   ~T548_t() = default;

   int exec()
      {
         {
            depth = 0;  // 0    1    2   3   4
            int arr[] = { -5, -10, -16, -3, -7 }; // -3 is largest
            uint sz = sizeof(arr) / sizeof(int);
            std::cout << hdr(sz);

            std::cout << "\n\n  Largest element in arr is  "
                      << largest_element(arr, 0, sz)
                      << ".\n" << std::endl;
         }
         {
            depth = 0;
            int arr[] = { -10, -5 }; // -5 is largest
            uint sz = sizeof(arr) / sizeof(int);
            std::cout << hdr(sz);

            std::cout << "\n\n  Largest element in arr is  "
                      << largest_element(arr, 0, sz)
                      << ".\n" << std::endl;
         }
         return 0;
      }

private: // methods

   int largest_element(const int* a, int begin, int past_end)
      {
         int result;
         int mid;
         int left_large;
         int right_large;

         assert(begin >= 0);
         assert(begin < past_end);

         std::cout << show(a, begin, past_end) << std::flush;

         if (past_end - begin == 1)
            result = a[begin];
         else {
            mid = (begin + past_end) / 2;
            left_large  = largest_element(a, begin, mid);
            right_large = largest_element(a, mid, past_end);

            if (left_large >= right_large)
               result = left_large;
            else
               result = right_large;
         }

         //STOP! draw tree here when begin == 1, and past_end == 2.
         depth -= 1;
         return result;
      }

   std::string show(const int* a, int b, int e)
      {
         std::stringstream ss;
         depth += 1;
         ss << "\n  a[" << b << " .. " << e-1 << "]    " 
            << depth << "   ";

         if(b > 0)
            ss << std::setw(4*b) << " ";

         for (int i = b; i < e; ++i)
            ss << std::setw(4) << a[i];

         return ss.str();
      }

   std::string hdr(uint sz)
      {
         std::stringstream ss;
         ss << "\n  "
            << "  b .. e"
            << std::setw(8) << "depth"
            << std::setw(4) << " ";
         for (uint i=0; i<sz; ++i)
            ss << i << "   ";
         return ss.str();
      }

}; // class T548_t

int main(int, char**)
{
   T548_t   t548;
   return t548.exec();
}

这是输出:

    b .. e   depth    0   1   2   3   4   
  a[0 .. 4]    1     -5 -10 -16  -3  -7
  a[0 .. 1]    2     -5 -10
  a[0 .. 0]    3     -5
  a[1 .. 1]    3        -10
  a[2 .. 4]    2            -16  -3  -7
  a[2 .. 2]    3            -16
  a[3 .. 4]    3                 -3  -7
  a[3 .. 3]    4                 -3
  a[4 .. 4]    4                     -7

  Largest element in arr is  -3.


    b .. e   depth    0   1   
  a[0 .. 1]    1    -10  -5
  a[0 .. 0]    2    -10
  a[1 .. 1]    2         -5

  Largest element in arr is  -5.

【讨论】:

    【解决方案2】:

    如果数组已排序并且您可以忽略每次递归的一半结果,这样的事情只会对您有所帮助。

    只需遍历元素即可找到最大的数字。你必须检查每个值

    【讨论】:

    • 如果数组已排序,那么他可以只返回最后一个元素(或者如果按降序排序,则返回第一个元素)。
    • 显然 :) 只是不需要对这个问题进行二分搜索
    • 这不是二分搜索。他正在查看数组中的每个元素。
    猜你喜欢
    • 2017-06-08
    • 2020-09-24
    • 2020-05-02
    • 2013-02-02
    • 2023-03-14
    • 2012-03-04
    • 2020-07-20
    • 1970-01-01
    • 2015-10-24
    相关资源
    最近更新 更多