Implementacja ciągu Fibonacciego ( rekurencja C++)

0

Jak zrobić to polecenie ? Dokonaj refaktoryzacji (przepisz kod źródłowy tak, aby dynamiczne lokowanie pamięci zastąpić rekurencją) załączonej implementacji ciągu Fibonacciego w programie c++.

  //implementacja ciągu Fibonnaciego z wykorzystaniem wskaźników i dynamicznej alokacji pamięci
#include <iostream>

using namespace std;

int main() {
    unsigned int n;
    cout << "Obliczam n początkowych wyraców ciągu Fibonacciego." << endl;
    cout << "Podaj n:" << endl;
    cin >> n;
    auto fib = new unsigned long long[n];
    if (n == 1) fib[0] = 1ull;
    else {
        fib[0] = 1ull;
        fib[1] = 1ull;
        for (unsigned int i = 2; i < n; i++) {
            fib[i] = fib[i - 1] + fib[i - 2];
        }
    }
    for (unsigned int i = 0; i < n; i++) {
        cout << "F(" << i + 1 << ")= " << fib[i] << endl;
    }
    delete[]fib;
    return 0;
}
1

Jaki masz problem z tym poleceniem? Nie rozumiesz go? Której części? Coś Ci nie wychodzi? Co? Coś nie działa? Co, w jaki sposób, dla jakich danych wejściowych?

W skrócie, zastany program w linijce 11. tworzy dynamicznie tablicę w stylu C — czemu nie używa po prostu std::vector jest zagadką; Twoim zadaniem jest usunąć tę tablicę z programu i zastąpić ją odwoływaniem się funkcji do samej siebie (rekurencją). Przyjrzyj się szczególnie linijce 17., ona powinna Cię mocno nakierować na porządaną formę samoodwoływania się.

0

Nie wiem jak zastąpić dokładnie tę funkcję rekurencją.

1

A wpisałeś to w google? Klasycnzy przykłąd rekurencji tłumaczy się na tym ciągu.
Dodatkowo możesz sobie zobaczyć wersję constexpress co sie generuje podczas kompilacji.

0

Żeby zrozumieć rekurencję, trzeba zrozumieć rekurencję. Nie ma innej drogi

2

main się skróci i wywoła osobną funkcję, która będzie korzystać z rekurencji.

Swoją drogą, z tego co widzę to programowania uczy cię ktoś niezbyt kompetentny. Dziwne, by uczyć początkującego użwania new i delete przed nauczeniem używania funkcji.

2
Nax napisał(a):

Nie wiem jak zastąpić dokładnie tę funkcję rekurencją.

Jasne, ale w czym dokładnie tkwi problem? Czy wiesz, co to jest rekurencja? Czy przyjrzałeś się, tak jak pisałem, linijce 17.? Jeśli tak, opisz — swoimi słowami — co się dzieje pomiędzy 12. a 19. linijką. Wydziel sobie nową funkcję — żeby się miało w ogóle co odwoływać samo do siebie¹ — i spróbuj sprawić, żeby robiła to samo, co one.

Jak sobie z czymś nie radzisz, to mów, z czym konkretnie — tylko wtedy da się pomóc, jak wiadomo, za co się brać.


¹ Wiem, wiem, operator paradoksalny, ciiii!

0

Czy jest ktoś kto mógłby rozwiązać to zadanie, ponieważ ciągle wychodzi mi źle ?

1

Bardzo wiele osób na tym forum mogłoby rozwiązać to zadanie — ale to Twoje zadanie, nie ich. Wyręczanie ludzi nie przynosi dobrych efektów.

Jeśli chcesz pomocy, otrzymasz ją — gdy opiszesz, co Ci wychodzi źle, co masz i na czym ta „złość” polega. Jeśli chcesz wyręczenia, to raczej się nie uda.

2

Nie wiem czy jest ktoś kto jest programistą i nie mógłby wykonać tego zadania. Ale my z reguły dajemy wędkę, nie rybę.

Mogę Ci podrzucić dwa materiały na temat innych rekurencyjnych algorytmów, które pozwolą Ci zrozumieć co się dzieje i jak, potem wrócisz do tego kodu i go rozwiążesz.

2
#include <iostream>

using namespace std;

unsigned long long fibonacci(unsigned int n) {
    if (n <= 1)
        return n;
    else
        return fibonacci(n - 1) + fibonacci(n - 2);
}

int main() {
    unsigned int n;
    cout << "Obliczam n początkowych wyrazów ciągu Fibonacciego." << endl;
    cout << "Podaj n:" << endl;
    cin >> n;
    for (unsigned int i = 1; i <= n; i++) {
        cout << "F(" << i << ")= " << fibonacci(i) << endl;
    }
    return 0;
}

@Althorion: coś mi tu nie gra w tym moim zapisie i potrzebuję kogoś kto by mi go sprawdził. Nie jestem do końca przekonany co do wyniku końcowego i chcę się upewnić, nie wiem czy o to chodziło dokładnie z ta rekurencją ?

0

Super, polecenie wykonane poprawnie. Kod działa i spełnia założenia zadania. Wszystko w porządku.

A jakie miałeś wątpliwości, to spróbujemy je rozwiać?

0

@Althorion: Miałem wątpliwości co do końcowego wyniku, ponieważ trochę wolno się ładuje ?

1
Nax napisał(a):

@Althorion: Miałem wątpliwości co do końcowego wyniku, ponieważ trochę wolno się ładuje ?

A no to bardzo słuszna uwaga, którą warto zanotować. Rekurencja w przypadku wysokiego "n" staje się bardzo powolna.
Pomyśl jak to wszystko zoptymalizować, bo jest jedno bardzo dobre rozwiązanie. Możesz rozpisać sobie drzewko rekurencji dla ułatwienia.

2
Nax napisał(a):

Miałem wątpliwości co do końcowego wyniku, ponieważ trochę wolno się ładuje ?

Bo to jest najgorszy moiżliwy sposób obliczania tego ciągu. To ma być jedynie demonstracja rekurencji.

Jeśli dopisać zapamiętywanie wyniku, to będzie to dużo szybsze.

unsigned long long fibonacci(unsigned int n) {
  static std::array<unsigned long long, 94> cache{};
  if (n < cache.size() && cache[n]) return cache[n];

  if (n <= 1)
      return n;
  else {
      auto r = fibonacci(n - 1) + fibonacci(n - 2);
      if (n < cache.size()) cache[n] = r;
      return r;
  }
}

https://godbolt.org/z/3n1Tc3q88

0

Zawsze mnie dziwiło, czemu w szkołach (czy na uczelniach nie-matematykom) się w ogóle pokazuje podejście rekurencyjne, a już w ogóle przykłada do tego tak wielką wagę…

Tak jak zauważyłeś, podejście do rekurencji „tak po prostu” skutkuje typowo wolnym programem (i/lub przepełnieniem stosu wywołań funkcji). Można to obchodzić — czy to przez memoizację (jak wyżej), czy przez rekurencję ogonową — i czasami faktycznie się tak robi, ale nigdy nie trafia się tak, że przepisuje się już działający kod iteracyjny na rekurencyjny…

Więc po co w ogóle sobie tym zawracać głowę? Czasami — niezbyt często — się trafi nam tak, że będziemy od razu widzieli, jak coś można rozwiązać rekurencyjnie¹, i wtedy faktycznie można naklepać na szybko kod, który nam się nasuwa i dopiero potem go ew. ulepszyć, jeśli będzie taka potrzeba. Ale jak nam się nie nasuwa? To nie, nie ma co na siłę — to nie jest dobry sposób pisania kodu.


¹ Głównie wtedy, jak nam łatwo jest opisać, jak coś się zmienia, ale trudno, jak do tego stanu dochodzi.

1 użytkowników online, w tym zalogowanych: 0, gości: 1