簡體   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