繁体   English   中英

我试图总结给定数组中的数字,使用递归,尝试了这段代码,但它不起作用。 为什么?

[英]I'm trying to sum up the numbers in a given array, using recursion , tried this code but it isn't working. Why?

#include <iostream>

   using namespace std;

   int sumByRecursion( int arr[]) {
        int sum = 0;
        int n = sizeof(arr)/sizeof(arr[0]);
        //n is the size of the array
        if (n == 0) {
            return sum;
        } else {
            n -= 1;
            for (int i=0;i=n;++i){
                arr[i]=arr[i+1];
            }
            return (sum + arr[0] + sumByRecursion( arr));
        }
    }

   int main() {
        int arr[]={2, 4, 6};
        sumByRecursion( arr);

        return 0;
    }
    

sumByRecursion 基于这个思想工作: 1-如果数组的大小为 0 “空数组”,则返回总和。 2-如果大小不为0“数组不为空”,将第一个元素求和,然后调用function,将数组的大小减1,对新数组进行sumByRecursion。

您需要将数组的大小传递给sumByRecursion例程。

您需要传递数组大小的原因是因为数组不跟踪自己的大小。

std::arraystd::vector这样的替代方案提供了查询它们的大小的能力,但是 C 风格的 arrays 不携带该信息。

std::size function 查询类型(在该上下文中是 C 样式数组)以计算大小。 一旦作为int arr[]参数传递,该arr类型就是int* ,它不再可以产生大小信息。

int arr[]参数是一种编写int* arr的方式,但向读者建议arr参数是 C 样式的数组。 如果正确完成,可以将其视为自记录代码 - 但是许多程序会将参数表示为int* arr所以,唉,它不是一个普遍的习语。

#include <cstddef>
#include <iterator>
#include <iostream>

using std::cout;
using std::size;
using std::size_t;

namespace {

int sumByRecursion(int arr[], size_t n) {
    if (n == 0) {
        return 0;
    } else {
        // Many C++ compilers do not perform tail recursion optimization.
        // But for those that do, this will thwart tail recursion optimization.
        return arr[0] + sumByRecursion(arr+1, n-1);
    }
}

} // anon

int main() {
    int arr[] = {2, 4, 6};
    auto arr_size = size(arr);
    auto sum = sumByRecursion(arr, arr_size);
    cout << sum << "\n";
}

一个(可悲的)常见错误:

int sumByRecursion( int arr[] )
{ // What do you think  ^^^^^  this is?

    int n = sizeof(arr)/sizeof(arr[0]);
    //      ^^^^^^^^^^^ Sorry, too late.
    // ...
}

正如评论部分已经指出的那样

在 function 内部,参数arr已衰减为 int* 类型,并且对数组中的元素数量一无所知。 理查德克里顿

简而言之: int sumByRecursion( int arr[])int sumByRecursion( int *arr)完全相同。 参数列表中的[]语法只不过是语法糖。 保罗麦肯齐

解决方案是将大小与指针一起传递,或者明确地作为单独的 function 参数或在 object 中,如std::spanstd::ranges::range

当然,另一种方法是传递std::cbegin()std ::cend() 返回的几个迭代器。


用于“将数组的大小减少 1”的代码可能是同样的误解造成的:

int sum = 0;
// ...
if (n == 0) {              // Ok...
    return sum;
} else {
    n -= 1;                // Okayish...
   
    for (int i=0;i=n;++i){ // 
        arr[i]=arr[i+1];   // <-- There's NO need to do all those copies!
    }                      // 

    return (sum + arr[0] + sumByRecursion( arr));
    //                                    ^^^^ This does NOT pass an array
}

Eljay回答显示了如何正确实现 OP 的算法。

只是为了好玩(1) ,一个堆栈友好的实现

#include <iostream>

int sumByRecursion(size_t n, int const* arr)
{
    // Stop the bloody recursion
    if ( n == 0 )
        return 0;
    if ( n == 1 )
        return arr[0];
    
    // Divide et impera
    size_t middle = n / 2;
    return sumByRecursion(middle, arr)
         + sumByRecursion(n - middle, arr + middle);
}

int main()
{
    int arr[] {2, 4, 6};

    std::cout << sumByRecursion(std::size(arr), arr) << '\n';
}

(1) 说真的,不要使用这个。 这是完全低效和无用的复杂。 请改用正确的算法

我可以使用算法Depth first search提供您问题的解决方案。

#include <iostream>
#include <vector>
using namespace std;
const int maximumSize=10;
vector<int> visited(maximumSize, 0);
int dfs(int current, int previous, vector<int>& input)
{
    if(visited[current]==1)
    {
        return 0;
    }
    visited[current]=1;
    int summarize=0;
    for(int next=(current+1); next<input.size(); ++next)
    {
        if(next==previous)
        {
            continue;
        }
        summarize+=dfs(next, current, input);
    }
    summarize+=input[current];
    return summarize;
}
void solve()
{
    vector<int> inputVector={2, 4, 6};
    cout<<dfs(0, -1, inputVector);
    return;
}
int main()
{
    solve();
    return 0;
}

结果如下:

12

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM