【问题标题】:Sum the positive elements of an array using recursion使用递归对数组的正元素求和
【发布时间】:2021-02-25 18:45:21
【问题描述】:

我正在学习递归并尝试计算数组的正元素的总和,但我不知道该怎么做。谁能帮帮我?

#include <iostream>
using namespace std;
    
int sum (int arr[],int n)
{
    if(n==-1)
    return  0;
    /*else if(arr[n]<0)
    return arr[n]+sum(arr,n+1) ;*/
    else
    return arr[n-1]+sum(arr , n-1);
        
}
    
int main()
{
    int  n , arr[n] ;
    cout<<"give the value of  n : " ; cin>>n;
    cout<<"give the values of the array ";
    for(int i=0;i<n;i++)
    cin>>arr[i];
    cout<<"the value of positive elements is  : " << sum(arr,n);
    return 0;
}

【问题讨论】:

  • 请澄清您的问题到底是什么,阅读How to Ask 了解更多信息。作为新用户,也请拨打tour。顺便说一句:如果您对值进行硬编码而不是手动输入它们会很有帮助,它可以让测试更容易,并且错误源更少。
  • main的第一行,n的值是多少? arr 有多大?
  • 与其他错误一样,在sum 中,如果n 为0,那么您进入else 子句并最终访问arr[-1],这不太可能是您想要的。
  • 即使你使用编译器扩展来启用 C++ 中的可变长度数组,在你用任何东西初始化 n 之前声明 int arr[n]; 是行不通的。它需要在声明时为arr 分配内存,而不是在您为n 分配值后追溯。

标签: c++ arrays c++11 recursion sum


【解决方案1】:

一些建议:

  1. 在 C++ 中(特别是从 C++11 开始),尽可能避免使用旧的 C 样式数组;改用std::vectorstd::dequestd::array(从C++11开始);

  2. 如果可能,使用模板编写通用代码;在这种情况下,请避免使用仅适用于 C 样式数组的 sum() 函数,而是编写一个模板函数,该函数也适用于 std::vector 等。

  3. 当你管理大小时,使用无符号整数(例如std::size_t),而不是有符号整数;这与标准 C++ 库保持一致,并避免大量有符号/无符号不一致。

鉴于您正在学习递归,我建议使用以下 sum() 函数

template <typename T>
int sum (T const & arr, std::size_t n)
 {
   return   ( arr[n] > 0 ? arr[n]        : 0)
          + (      n > 0 ? sum(arr, n-1) : 0);
 }

观察第一行,其中

( arr[n] > 0 ? arr[n]        : 0)

arr[n] 加到总和中当且仅当当且仅当大于零(否则加零)

还要观察第二行,其中

+ (      n > 0 ? sum(arr, n-1) : 0);

如果n 大于零,则递归继续(添加sum(arr, n-1))。

以下是使用std::vector的完整编译示例。

#include <vector>
#include <iostream>

template <typename T>
int sum (T const & arr, std::size_t n)
 {
   return   ( arr[n] > 0 ? arr[n]        : 0)
          + (      n > 0 ? sum(arr, n-1) : 0);
 }

int main()
 {
   std::size_t      dim;
   std::vector<int> vec;

   std::cout << "give the value of  n : " ; std::cin >> dim;
   std::cout << "give the values of the array ";

   vec.resize(dim);

   for ( auto & val : vec )
      std::cin >> val;

  
   std::cout << "the value of positive elements is  : " 
      << (dim > 0u ? sum(vec, dim-1u) : 0) << std::endl;
 }

【讨论】:

  • 我是这种语言的新手,但非常感谢您的建议!
  • @AdrianMole - 哦!可怕的错误。已更正。谢谢。
  • @WalidWalid - 我的代码中有一个可怕的错误(请参阅 Adrian Mole 评论);已更正。
【解决方案2】:

您的递归函数应该返回三个值之一:

  1. 如果我们已经到达数组的末尾,则返回零
  2. 否则,如果“当前”数组元素为负数或零,则返回“下一个”递归
  3. 否则,如果“当前”元素为正数,则返回该元素的 sum 和下一次递归。

在每次递归调用中,我们需要: (a) 增加“当前”元素的索引; (b) 减少数组中剩余的元素数量。对于 (a),我们可以利用作为函数参数传递的数组衰减到指向其第一个元素的指针这一事实,因此我们可以在该指针上添加一个以进行递归调用:

int sum(int arr[], int n)
{
    if (n <= 0) return 0; // Reached the end of the array: return zero
    if (*arr <= 0) return sum(arr + 1, n - 1); // Non-positive number: skip it
    return sum(arr + 1, n - 1) + *arr;  // Add this number to the recursion result!
}

请随时要求任何进一步的澄清和/或解释。


编辑:另外,如果您坚持使用可变长度数组(VLA - 不是标准 C++),那么您需要在阅读完用户给定的n 的值。但我建议使用固定(最大)大小,例如:int n, arr[100];

【讨论】:

  • 你可以保存一个else。
  • @Surt Indeed(见编辑)。我被困在两种风格之间:在第二种和第三种情况下使用else(为了清楚起见)或根本不使用它。我现在一直不使用else
  • 你好!你的回答也很有效,但在某些情况下,比如当我选择 2 作为数组长度不起作用时,你对这个错误有什么了解吗
  • @WalidWalid 我无法在数组长度为 2(甚至 1)的情况下重现您的错误。您是否进行了最后一段中建议的更改?
  • 但是如果我们固定大小为什么我们在函数的参数上添加 n !注意:如果我固​​定大小并在仍然存在相同问题后更改它
【解决方案3】:

...学习递归并尝试计算数组的正元素之和...

考虑如果数组中只有 1 个元素该怎么办,然后编写代码。
return (arr[0] &gt; 0) ? arr[0] : 0;

否则将问题分解为更小的子问题。

其他人已经回答了如何,但使用递归是一种迭代方式——只是减小数组大小。递归深度可以是O(n)

我建议将问题的大小除以二。
此替代方案使用的深度要小得多:O(log n)

int sum (const int arr[], int n) {
  if (n <= 1) {
    return (n > 0 && arr[0] > 0) ? arr[0] : 0;
  }
  int left_size = n/2;
  return sum(arr, left_size) + sum(arr + left_size, n - left_size);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-09-22
    • 1970-01-01
    • 2018-12-02
    • 1970-01-01
    • 2017-10-24
    • 2023-01-23
    • 2019-04-29
    相关资源
    最近更新 更多