Co jest rekurencja i kiedy należy go używać?

głosy
121

Jednym z tematów, który wydaje się pochodzić regularnie na listach dyskusyjnych i dyskusji online jest zasadność (lub jej brak) dokonywania Informatyki stopniu. Argumentem, który wydaje się pochodzić czas i ponownie do negatywnej ze stron jest to, że zostały one kodowania dla pewnej liczby lat i nigdy nie używane rekursji.

Więc pytanie brzmi:

  1. Co jest rekurencja?
  2. Kiedy chciałbym użyć rekurencji?
  3. Dlaczego ludzie nie używaj rekursji?
Utwórz 06/08/2008 o 03:29
źródło użytkownik
W innych językach...                            


40 odpowiedzi

głosy
86

Istnieje wiele dobrych wyjaśnień rekursji w tym wątku, to odpowiedź brzmi, dlaczego nie powinno się go używać w większości języków. * W większości dużych wdrożeń językowych imperatyw (czyli każda większa realizacja C, C ++, Basic, Python Ruby, Java i C #) iteracja jest znacznie korzystniejsze rekursji.

Aby zrozumieć, dlaczego, chodzić po schodach, że powyższe języki użyć do wywołania funkcji:

  1. Przestrzeń jest wykute na stosie dla argumentów funkcja i zmiennych lokalnych
  2. Argumenty funkcji są kopiowane do nowego miejsca
  3. Sterowanie przechodzi do funkcji
  4. uruchamia kod funkcji za
  5. Wynik funkcja jest kopiowany do wartości zwracanej
  6. stos jest przewinięta do swojej poprzedniej pozycji
  7. sterowanie powraca do miejsca, gdzie funkcja została wywołana

Robi wszystko z tych etapów wymaga czasu, zwykle nieco więcej niż potrzeba do iteracji pętli. Jednak prawdziwym problemem jest to w kroku 1. Kiedy wiele programów zaczynają one przeznaczyć jeden kawałek pamięci na ich stosie, a kiedy zabraknie tej pamięci (często, ale nie zawsze z powodu rekursji), program wywala ze względu na przepełnienie stosu .

Tak więc w tych językach rekurencji jest wolniejszy, a to sprawia, że ​​podatny na upaść. Nadal istnieją pewne argumenty za użyciem go jednak. W ogóle, kod napisany rekurencyjnie jest krótszy i nieco bardziej elegancka, gdy wiesz, jak go odczytać.

Jest to technika, która realizatorzy językowe mogą używać nazywany optymalizacji połączeń ogon , który może wyeliminować niektóre klasy przepełnienia stosu. Umieścić zwięźle: jeśli wyrażenie powrót funkcji jest po prostu wynikiem wywołania funkcji, wtedy nie trzeba dodać nowy poziom na stosie, można ponownie wykorzystać obecną jeden dla funkcji do której dzwonimy. Niestety, niewiele nadrzędne języka implementacje mają optymalizacja ogon wywołanie wbudowany.

* Kocham rekursji. Mój ulubiony język statyczna ma w ogóle nie używać pętli, rekurencja jest jedynym sposobem, aby coś zrobić wielokrotnie. Po prostu nie sądzę, że rekurencja jest generalnie dobrym pomysłem w językach, które nie są dostrojone do niego.

** Przy okazji Mario, typowy nazwę dla swojej funkcji ArrangeString jest „join”, i byłbym zaskoczony, gdyby język z wyboru nie mają już implementację niego.

Odpowiedział 06/08/2008 o 06:09
źródło użytkownik

głosy
63

Prosty przykład angielski rekursji.

A child couldn't sleep, so her mother told her a story about a little frog,
    who couldn't sleep, so the frog's mother told her a story about a little bear,
         who couldn't sleep, so the bear's mother told her a story about a little weasel... 
            who fell asleep.
         ...and the little bear fell asleep;
    ...and the little frog fell asleep;
...and the child fell asleep.
Odpowiedział 04/05/2010 o 17:38
źródło użytkownik

głosy
49

W najbardziej podstawowym sensie informatycznym, rekurencja jest funkcją, która nazywa siebie. Załóżmy, że masz połączoną strukturę listy:

struct Node {
    Node* next;
};

I chcesz dowiedzieć się, jak długo związana jest lista można to zrobić z rekursji:

int length(const Node* list) {
    if (!list->next) {
        return 1;
    } else {
        return 1 + length(list->next);
    }
}

(Może to być oczywiście wykonane z pętli, a także, ale jest użyteczny jako ilustracji koncepcji)

Odpowiedział 04/05/2010 o 12:25
źródło użytkownik

głosy
46

Ilekroć funkcja nazywa się, tworząc pętlę, a potem to rekurencji. Jak z niczego istnieją dobre i złe zastosowań zastosowań dla rekursji.

Najprostszym przykładem jest ogon rekursji gdzie to ostatnia linia funkcji jest wywołanie sobie;

int FloorByTen(int num)
{
    if (num % 10 == 0)
        return num;
    else
        return FloorByTen(num-1);
}

Jednak to jest kulawy, prawie bez sensu przykładem, ponieważ może być łatwo zastąpione przez bardziej wydajne iteracji. Po tym wszystkim, rekursja cierpi z napowietrznych wywołania funkcji, na przykład powyżej mogą być znaczące w porównaniu z operacją w samej funkcji.

Więc cały powód, aby zrobić rekursji zamiast iteracji należy skorzystać z stosu wywołań zrobić jakiś sprytny rzeczy. Na przykład, jeśli wywołanie funkcji wiele razy z różnymi parametrami wewnątrz samej pętli to jest to droga do osiągnięcia rozgałęzienia . Klasycznym przykładem jest Trójkąt Sierpińskiego .

wprowadzić opis obrazu tutaj

można wyciągnąć jeden z tych bardzo prosto z rekursji, gdzie gałęzie stos wywołań w 3 kierunkach:

private void BuildVertices(double x, double y, double len)
{
    if (len > 0.002)
    {
        mesh.Positions.Add(new Point3D(x, y + len, -len));
        mesh.Positions.Add(new Point3D(x - len, y - len, -len));
        mesh.Positions.Add(new Point3D(x + len, y - len, -len));
        len *= 0.5;
        BuildVertices(x, y + len, len);
        BuildVertices(x - len, y - len, len);
        BuildVertices(x + len, y - len, len);
    }
}

Jeśli spróbujesz zrobić to samo z iteracji myślę znajdziesz to zajmuje dużo więcej kodu do wykonania.

Inne przypadki wspólnego użytku może zawierać przechodzących hierarchie, roboty np witryn porównania katalogów itp

Wniosek

W praktyce oznacza to, rekurencja największy sens, gdy trzeba iteracyjny rozgałęzienia.

Odpowiedział 04/05/2010 o 14:33
źródło użytkownik

głosy
28

Rekurencja jest metodą rozwiązywania problemów na podstawie dziel i rządź mentalności. Podstawowym założeniem jest to, że ma oryginalny problem i podzielić ją na mniejsze (łatwiej rozwiązane) wystąpień sobie, rozwiązać te mniejsze instancje (zwykle po ponownym użyciem tego samego algorytmu), a następnie zamontować je do ostatecznego rozwiązania.

Kanonicznym przykładem jest okresowo generować silnia n. Silnia n jest obliczana przez pomnożenie wszystkich liczb od 1 do n. Iteracyjny rozwiązanie w C # wygląda następująco:

public int Fact(int n)
{
  int fact = 1;

  for( int i = 2; i <= n; i++)
  {
    fact = fact * i;
  }

  return fact;
}

Nie ma nic dziwnego iteracyjnego rozwiązania i powinna ona sensu nikogo znanego z C #.

Rekursywne rozwiązanie znajduje uznając, że n-ta jest silnia n * Fakt (n-1). Lub inaczej mówiąc, jeśli wiesz, co dana liczba Silnia to można obliczyć następny. Oto rozwiązanie rekurencyjne w języku C #:

public int FactRec(int n)
{
  if( n < 2 )
  {
    return 1;
  }

  return n * FactRec( n - 1 );
}

Pierwsza część tej funkcji jest znany jako przypadek bazowy (lub czasami Straży klauzuli) i to, co zapobiega algorytm działa od zawsze. To po prostu zwraca wartość 1, gdy funkcja jest wywoływana o wartości 1 lub mniej. Druga część jest bardziej interesująca jest znany jako rekurencyjnych kroku . Tutaj nazywamy ten sam sposób za pomocą nieco zmodyfikowanego parametru (to zmniejszyć je do 1), a następnie pomnożenie wyniku z naszym kopii n.

Kiedy po raz pierwszy spotkałem może to być rodzaj mylące, więc jest to pouczające zbadać, jak to działa, jeśli jest uruchomiony. Wyobraźmy sobie, że nazywamy FactRec (5). Wchodzimy w rutynę, nie są odbierane przez przypadek bazowy i tak kończy się tak:

// In FactRec(5)
return 5 * FactRec( 5 - 1 );

// which is
return 5 * FactRec(4);

Jeśli będziemy ponownie wprowadzić metodę z parametrem 4 my znowu nie zatrzymany przez klauzuli straży i tak kończy się na:

// In FactRec(4)
return 4 * FactRec(3);

Jeżeli podstawimy tę wartość powrotną do zwracanej wartości powyżej otrzymujemy

// In FactRec(5)
return 5 * (4 * FactRec(3));

To powinno dać wskazówkę co do tego, jak ostateczne rozwiązanie jest przybył tak szybko będziemy śledzić i pokazać każdy krok na drodze w dół:

return 5 * (4 * FactRec(3));
return 5 * (4 * (3 * FactRec(2)));
return 5 * (4 * (3 * (2 * FactRec(1))));
return 5 * (4 * (3 * (2 * (1))));

Że ostateczny podstawienie dzieje się, gdy przypadek bazowy jest wyzwalany. W tym momencie mamy proste algrebraic formułę do rozwiązania co przekłada się bezpośrednio do definicji silni w pierwszej kolejności.

To pouczające, aby pamiętać, że każde wezwanie do wyników metody zarówno w przypadku bazowego jest wyzwalany lub wywołanie tej samej metody, gdzie parametry są bliżej do przypadku bazowego (często nazywany jest wywołanie rekurencyjne). Jeśli tak nie jest, to metoda będzie trwał wiecznie.

Odpowiedział 06/08/2008 o 03:54
źródło użytkownik

głosy
12

Rekurencja jest rozwiązywanie problemu z funkcji, która nazywa siebie. Dobrym tego przykładem jest funkcja silnia. Silnia jest problemem Math gdzie silnia 5, na przykład, 5 * 4 * 3 * 2 * 1 Funkcja rozwiązuje ten C # dla dodatnich liczb całkowitych (nie testowany - może to być błąd).

public int Factorial(int n)
{
    if (n <= 1)
        return 1;

    return n * Factorial(n - 1);
}
Odpowiedział 04/05/2010 o 12:29
źródło użytkownik

głosy
9

Rozważmy stary, dobrze znany problem :

W matematyce The największy wspólny dzielnik (NWD) ... się z dwóch lub większej liczby niezerowych liczb całkowitych, jest największą liczbą całkowitą dodatnią, która dzieli numery bez reszty.

Definicja GCD jest zaskakująco prosta:

definicja nWD

gdzie mod jest operatorem modulo (to jest reszta z dzielenia liczby całkowitej).

W języku angielskim, to definicja mówi, że największy wspólny dzielnik dowolnej liczby i zerowym jest liczba, a największy wspólny dzielnik dwóch liczb m i n jest największy wspólny dzielnik n a pozostała po podzieleniu m przez n .

Jeśli chcesz wiedzieć, dlaczego to działa, patrz artykuł w Wikipedii na temat algorytmu Euklidesa .

Załóżmy obliczyć GCD (10, 8) jako przykład. Każdy krok jest równa jeden tuż przed nim:

  1. GCD (10, 8)
  2. GCD (10, 10 mod 8)
  3. GCD (8: 2)
  4. GCD (8, 8 mod 2)
  5. GCD (2, 0)
  6. 2

W pierwszym etapie 8 nie jest równa zeru, więc druga część definicji dotyczy. 10 mod 8 = 2, ze względu na 8 do 10, gdy wychodzi z dalszej części 2. W etapie 3, druga część odnosi się, ale tym razem wynosił 8 mod 2 = 0, ponieważ dwa podziały 8 bez reszty. W punkcie 5, drugi argument jest 0, więc odpowiedź brzmi: 2.

Zauważyłeś, że NWD zarówno po lewej i prawej stronie znaku równości wydaje? Matematyk powiedziałby definicja ta jest rekurencyjna, ponieważ ekspresja jesteś definiowanie powtarza się wewnątrz jego definicji.

definicje rekurencyjne wydają się być elegancki. Na przykład, rekurencyjna definicja sumy listy jest

sum l =
    if empty(l)
        return 0
    else
        return head(l) + sum(tail(l))

gdzie headjest pierwszy element na liście i tailjest reszta listy. Zauważ, że sumpowtarza się wewnątrz jej definicji na końcu.

Może wolisz maksymalną wartość z listy zamiast:

max l =
    if empty(l)
        error
    elsif length(l) = 1
        return head(l)
    else
        tailmax = max(tail(l))
        if head(l) > tailmax
            return head(l)
        else
            return tailmax

Można zdefiniować mnożenia liczb całkowitych nieujemnych rekurencyjnie aby przekształcić go w szereg dodatków:

a * b =
    if b = 0
        return 0
    else
        return a + (a * (b - 1))

Jeśli to nieco o przekształcenie mnożenia na szereg dodatków nie ma sensu, spróbuj rozszerza kilka prostych przykładów, aby zobaczyć jak to działa.

Scalanie sort ma piękny rekurencyjną definicję:

sort(l) =
    if empty(l) or length(l) = 1
        return l
    else
        (left,right) = split l
        return merge(sort(left), sort(right))

Definicje rekurencyjne są wszędzie wokół, jeśli wiesz, czego szukać. Zauważ, jak wszystkie te definicje mają bardzo proste przypadki bazowe, np , gcd (m, 0) = M. Rekurencyjnego przypadki Whittle z dala na problem, aby dostać się do łatwych odpowiedzi.

Z tego zrozumienia, można docenić inne algorytmy w artykule Wikipedii na rekursji !

Odpowiedział 04/05/2010 o 14:58
źródło użytkownik

głosy
9

Rekursji odnosi się do metody, która rozwiązuje problem rozwiązania mniejszą wersję problemu, a następnie za pomocą tego rezultatu oraz dodatkowe, obliczenie do sformułowania odpowiedzi pierwotnej problemu. Często w procesie rozwiązywania mniejszą wersję, metoda będzie rozwiązać jeszcze mniejszą wersję problemu, i tak dalej, aż do osiągnięcia „przypadek bazowy”, który jest trywialny rozwiązać.

Na przykład, aby obliczyć silnię dla numeru X, można reprezentować jako X times the factorial of X-1. Zatem metoda „recurses”, aby znaleźć silni X-1, a następnie mnoży przez cokolwiek to ma Xdać ostateczną odpowiedź. Oczywiście, aby znaleźć silni X-1, będzie to pierwsze obliczenia silni X-2, i tak dalej. Sprawa byłaby podstawa, gdy Xjest 0 lub 1, w którym to przypadku nie wie, aby powrócić 1od 0! = 1! = 1.

Odpowiedział 04/05/2010 o 12:26
źródło użytkownik

głosy
9
  1. Funkcja, która nazywa się
  2. Gdy funkcja ta może być (łatwo) rozkłada się w prosty sposób powiększona o tej samej funkcji, o niektórych mniejszych części problemu. powiedziałbym raczej, że to sprawia, że ​​dobrym kandydatem do rekursji.
  3. Robią!

Kanonicznym przykładem jest silnia który wygląda tak:

int fact(int a) 
{
  if(a==1)
    return 1;

  return a*fact(a-1);
}

W ogóle, rekurencja niekoniecznie jest szybka (overhead wywołanie funkcji wydaje się być wysokie, ponieważ funkcje rekurencyjne wydają się być małe, patrz wyżej) i może cierpieć z powodu pewnych problemów (przepełnienia stosu ktoś?). Niektórzy mówią, że wydają się być trudne do uzyskania „prawo” w nietrywialnych przypadków, ale ja naprawdę nie kupować w tym. W niektórych sytuacjach, rekurencja największy sens i jest najbardziej elegancki i przejrzysty sposób napisać szczególną funkcję. Należy zauważyć, że niektóre języki faworyzować rekurencyjnych rozwiązań i optymalizacji ich znacznie więcej (LISP przychodzi do głowy).

Odpowiedział 06/08/2008 o 03:35
źródło użytkownik

głosy
7

Funkcji rekurencyjnej jest taki, który nazywa siebie. Najczęstszym powodem Znalazłem go używać przemierza strukturę drzewa. Na przykład, jeśli mam TreeView z wyboru (myślę instalacji nowego programu „wybierz funkcje do zainstalowania” strona), może chcę przycisk „zaznacz wszystko”, co byłoby coś jak to (Pseudokod):

function cmdCheckAllClick {
    checkRecursively(TreeView1.RootNode);
}

function checkRecursively(Node n) {
    n.Checked = True;
    foreach ( n.Children as child ) {
        checkRecursively(child);
    }
}

Więc widać, że checkRecursively najpierw sprawdza węzeł, który jest przekazywany, a następnie zwraca się do każdego z dzieci, które węzła.

Trzeba być nieco ostrożny z rekursji. Jeśli do nieskończonej pętli rekurencyjnej, dostaniesz wyjątek przepełnieniem stosu :)

Nie mogę myśleć o powód, dla którego ludzie nie powinni go używać, gdy stosowne. Jest to przydatne w pewnych okolicznościach, a nie w innych.

Myślę, że dlatego, że jest interesująca technika, niektórzy programiści może skończyć używając go częściej niż powinni, bez realnego uzasadnienia. Dało rekursji złe imię w niektórych kręgach.

Odpowiedział 06/08/2008 o 03:44
źródło użytkownik

głosy
5

Rekursji jest ekspresja bezpośrednio lub pośrednio odwołanie się.

Rozważmy akronim rekurencyjny jako prosty przykład:

  • GNU to skrót od GNU to Nie Unix
  • PHP oznacza PHP: Hypertext Preprocessor
  • YAML oznacza YAML nie jest Markup Language
  • WINO oznacza Wine Is Not Emulator
  • VISA oznacza Visa International Service Association

Więcej przykładów na Wikipedii

Odpowiedział 04/05/2010 o 12:56
źródło użytkownik

głosy
5

Oto prosty przykład: Ile elementów w zestawie. (Istnieją lepsze sposoby liczą rzeczy, ale jest to miły prosty rekurencyjny przykład).

Po pierwsze, musimy dwie reguły:

  1. jeśli zestaw jest pusty, liczba elementów w zbiorze wynosi zero (duh!).
  2. jeśli zestaw nie jest pusty, liczba jest jeden plus liczba elementów w zbiorze po jeden element jest usuwany.

Załóżmy, że masz zestaw jak poniżej: [xxx]. niech policzyć ile przedmiotów istnieją.

  1. zestaw jest [xxx], która nie jest pusta, więc możemy zastosować regułę 2. Kasa jest jeden plus liczba elementów w [xx] (tzn usunęliśmy element).
  2. zestaw jest [xx], więc ponownie zastosować regułę 2: numer jeden w pozycji + [x].
  3. zestaw jest [x], która wciąż pasuje regułę 2: jeden numer + elementów w [].
  4. Teraz zestaw jest [], który pasuje Zasada 1: liczba jest zerem!
  5. Teraz wiemy, że odpowiedź w kroku 4 (0), możemy rozwiązać krok 3 (1 + 0)
  6. Podobnie teraz, że znamy odpowiedź w kroku 3 (1), możemy rozwiązać krok 2 (1 + 1)
  7. I wreszcie teraz, że znamy odpowiedź w kroku 2 (2), możemy rozwiązać krok 1 (1 + 2) i uzyskać liczbę elementów w [xxx], który jest 3. Brawo!

Możemy reprezentować to jako:

count of [x x x] = 1 + count of [x x]
                 = 1 + (1 + count of [x])
                 = 1 + (1 + (1 + count of []))
                 = 1 + (1 + (1 + 0)))
                 = 1 + (1 + (1))
                 = 1 + (2)
                 = 3

Przy stosowaniu rekurencyjną rozwiązanie, które zwykle mają co najmniej 2 zasad:

  • podstawą, prosta sprawa, w której stwierdza się, co się dzieje, gdy masz „zużyty” wszystkich swoich danych. Zazwyczaj jest to jakiś wariant „jeśli jesteś z danymi do procesu, odpowiedź jest X”
  • rekurencyjne przepis, który stanowi, co się dzieje, jeśli jeszcze dane. Zazwyczaj jest to jakaś reguła, która mówi „coś zrobić, aby Twoje dane ustawione mniejsze i ponownie zastosować reguły do ​​mniejszego zbioru danych.”

Jeśli tłumaczymy wyżej do Pseudokod, otrzymujemy:

numberOfItems(set)
    if set is empty
        return 0
    else
        remove 1 item from set
        return 1 + numberOfItems(set)

Jest dużo bardziej użyteczne przykłady (przejeżdżające drzewo, na przykład), które jestem pewien, że inni ludzie będą obejmować.

Odpowiedział 06/08/2008 o 04:12
źródło użytkownik

głosy
5

Rekurencja działa najlepiej z tym, co lubię nazywać „fraktalne problemów”, gdzie mamy do czynienia z wielkim rzeczą, która jest wykonana z mniejszymi wersjami tej wielkiej rzeczy, z których każdy jest nawet mniejsza wersja big thing, i tak dalej. Jeśli kiedykolwiek przemierzać lub przeszukiwać coś w rodzaju drzewa lub zagnieżdżonych identycznych struktur, masz problem, który może być dobrym kandydatem do rekursji.

Ludzie unikać rekursji dla wielu powodów:

  1. Większość ludzi (w tym ja) obniżyć swoje zęby na programowaniu programowania proceduralnego lub obiektowego w przeciwieństwie do programowania funkcyjnego. Do takich ludzi, iteracyjny podejście (zazwyczaj przy pętli) czuje się bardziej naturalne.

  2. Ci z nas, którzy cięcia zęby na programowaniu programowania proceduralnego lub obiektowego często kazano unikać rekurencji, ponieważ jest podatny na błędy.

  3. Jesteśmy często mówią, że rekurencja jest powolny. Wywoływanie i powrocie z rutyny wielokrotnie wymaga dużo stos pchania i popping, który jest wolniejszy niż zapętlenie. Myślę, że niektóre języki obsłużyć to lepiej niż inni, a te języki są najprawdopodobniej nie te, w których dominującym paradygmatem jest proceduralne lub obiektowe.

  4. Przez co najmniej kilka języków programowania użyłem, pamiętam słuchu zalecenia, aby nie używać rekurencji jeśli robi się po przekroczeniu pewnej głębokości, ponieważ jego stos nie jest głęboka.

Odpowiedział 06/08/2008 o 04:12
źródło użytkownik

głosy
4

1) Sposób jest rekurencyjne, jeżeli może wywołać się; bezpośrednio:

void f() {
   ... f() ... 
}

lub pośrednio:

void f() {
    ... g() ...
}

void g() {
   ... f() ...
}

2) Kiedy używać rekurencji

Q: Does using recursion usually make your code faster? 
A: No.
Q: Does using recursion usually use less memory? 
A: No.
Q: Then why use recursion? 
A: It sometimes makes your code much simpler!

3.) Ludzie korzystają z rekurencji tylko wtedy, gdy jest to bardzo skomplikowane, aby napisać kod iteracyjny. Na przykład, techniki przechodzenie drzewa jak przedsprzedaży, postorder mogą być wykonane zarówno iteracyjny i rekurencyjne. Ale zazwyczaj używamy rekurencyjnych ze względu na jego prostotę.

Odpowiedział 11/03/2014 o 10:47
źródło użytkownik

głosy
4

Rekurencyjna stwierdzenie jest taki, w którym można zdefiniować proces, co robić dalej jako kombinacja wejść i co zrobiono.

Na przykład, weźmy silnia:

factorial(6) = 6*5*4*3*2*1

Ale to łatwo zrozumieć, silni (6) również jest:

6 * factorial(5) = 6*(5*4*3*2*1).

Tak ogólnie:

factorial(n) = n*factorial(n-1)

Oczywiście, najtrudniejsza rzeczą rekursji jest, że jeśli chcemy zdefiniować rzeczy w kategoriach tego, co zostało już zrobione, nie musi być jakieś miejsce, aby rozpocząć.

W tym przykładzie, po prostu złożyć szczególny przypadek definiując silnia (1) = 1.

Teraz widzimy go od dołu do góry:

factorial(6) = 6*factorial(5)
                   = 6*5*factorial(4)
                   = 6*5*4*factorial(3) = 6*5*4*3*factorial(2) = 6*5*4*3*2*factorial(1) = 6*5*4*3*2*1

Ponieważ zdefiniowane silnia (1) = 1, to osiągnąć „dół”.

Ogólnie rzecz biorąc, procedury rekurencyjne się z dwóch części:

1) rekurencyjne część, która określa pewne procedury w zakresie nowych wejść w połączeniu z tym, co masz „już zrobione” przez tą samą procedurą. (tj factorial(n) = n*factorial(n-1))

2) Część bazowa, która zapewnia, że proces nie powtórzyć zawsze dając mu trochę miejsca, aby uruchomić (tj factorial(1) = 1)

To może być nieco mylące, aby dostać się wokół twojej głowie na początku, ale wystarczy spojrzeć na pęczek przykładów i wszystko to powinno przyjść razem. Jeśli chcesz znacznie głębsze zrozumienie koncepcji, badanie indukcji matematycznej. Należy również pamiętać, że niektóre języki optymalizacji dla wywołań rekurencyjnych podczas gdy inne nie. Jest to dość łatwe do wykonania szalenie powolne funkcje rekurencyjne, jeśli nie jesteś ostrożny, ale są też techniki do podawania ich do wydajnych w większości przypadków.

Mam nadzieję że to pomoże...

Odpowiedział 04/05/2010 o 14:30
źródło użytkownik

głosy
4

Lubię tę definicję:
W rekursji, rutynowa rozwiązuje niewielką część samego problemu, dzieli problem na mniejsze kawałki, a następnie zwraca się rozwiązać każdy z mniejszych kawałków.

Lubię też Steve McConnells dyskusji rekursji w Kodeksie wypełnić gdzie krytykuje przykłady stosowanych w książkach Computer Science on rekursji.

Nie używaj rekursji dla silni lub liczb Fibonacciego

Jeden problem z podręczników nauk komputerowych jest to, że stanowią one głupie przykłady rekursji. Typowe przykłady obliczania silni lub obliczanie Fibonacciego. Rekurencja jest potężnym narzędziem, a to naprawdę głupi, aby używać go w żadnym z tych przypadków. Jeśli programista, który pracował dla mnie wykorzystywane rekursji do obliczania silni, chciałbym zatrudnić kogoś innego.

Myślałem, że to bardzo ciekawy punkt do podnoszenia i mogą być powodem dlaczego rekurencji jest często niezrozumiany.

EDIT: To nie była odpowiedź na dig DAV - Jeszcze nie widział tę odpowiedź, kiedy pisał ten

Odpowiedział 04/05/2010 o 12:29
źródło użytkownik

głosy
3

Na przykład: Określenie cykliczna schodów jest: schodów składa się z: - pojedynczy etap i schody (rekurencji) - lub tylko jeden krok (rozwiązanie)

Odpowiedział 04/05/2010 o 14:34
źródło użytkownik

głosy
3

Dobrze, że to całkiem przyzwoity definicja masz. I wikipedia ma dobrą definicję zbyt. Więc dodam kolejny (chyba gorzej) definicję dla Ciebie.

Kiedy ludzie odnoszą się do „rekurencja”, oni zwykle mówią o funkcji oni pisemną, która nazywa się wielokrotnie, aż to się robi z jego pracy. Rekurencja mogą być pomocne przy jeździe hierarchii w strukturach danych.

Odpowiedział 04/05/2010 o 12:27
źródło użytkownik

głosy
3

Rekursja na rozwiązane problemu: nic nie robić, skończysz.
Rekursja na otwartym problemem: zrobić następny krok, a następnie przeszukanie na odpoczynek.

Odpowiedział 06/08/2008 o 04:32
źródło użytkownik

głosy
2

Jest to stare pytanie, ale chcę dodać odpowiedź z logistycznego punktu widzenia (czyli nie z punktu widzenia poprawności algorytmu lub punktu widzenia wydajności).

Używam Java do pracy i Java nie obsługuje funkcji zagnieżdżonych. Jako takie, jeśli chcę zrobić rekursji, mogę zdefiniować funkcję zewnętrznego (który istnieje tylko dlatego, że mój kod wpada przeciwko biurokratycznej reguły Java), czy może mam byłaby kod całkowicie (co naprawdę nienawidzę robić).

Tak więc, często uniknąć rekursji oraz działanie użycie zamiast stosu, ponieważ sama rekurencja jest zasadniczo operacja stos.

Odpowiedział 30/08/2014 o 11:09
źródło użytkownik

głosy
2

Funkcji rekurencyjnej jest funkcją, która zawiera wezwanie do siebie. Cykliczna struktura jest struktura, która zawiera wystąpienie siebie. Można łączyć te dwie postaci rekurencyjnej klasie. Kluczową częścią cyklicznej pozycji jest to, że zawiera instancję / wezwanie siebie.

Rozważmy dwa lustra naprzeciw siebie. Widzieliśmy estetyczny efekt nieskończoności ich wykonania. Każdy odbicia jest wystąpienie lustro, które jest zawarte w innym przypadku lustra, itp lustro zawierający odbicie sobie jest rekursji.

Wyszukiwania binarne drzewo jest dobrym przykładem programowanie rekursji. Struktura jest rekurencyjnego z każdego węzła zawierającej 2 wystąpień węzła. Funkcje do pracy na wyszukiwaniu binarnym drzewie są również rekurencyjne.

Odpowiedział 04/05/2010 o 17:46
źródło użytkownik

głosy
2

W prostym języku angielskim: Załóżmy, że można zrobić 3 rzeczy:

  1. Weź jedno jabłko
  2. Zanotować znaki tally
  3. Policzyć znaki tally

Masz dużo jabłek przed sobą na stole i chcesz wiedzieć, ile jabłek istnieją.

start
  Is the table empty?
  yes: Count the tally marks and cheer like it's your birthday!
  no:  Take 1 apple and put it aside
       Write down a tally mark
       goto start

Proces powtarzając to samo, aż skończysz nazywa rekurencji.

Mam nadzieję, że jest to „zwykły angielski” odpowiedź szukasz!

Odpowiedział 04/05/2010 o 14:09
źródło użytkownik

głosy
1

Najprostsza definicja rekursji jest „self-reference”. Funkcja, która odnosi się do siebie, czyli wywołuje sama w sobie jest rekurencyjny. Najważniejszą rzeczą, aby pamiętać, że funkcja rekurencyjna musi mieć „przypadek bazowy”, czyli warunek, że jeśli nie powoduje to prawda nazywać się, a tym samym zakończenia rekurencji. W przeciwnym razie trzeba będzie nieskończoną rekurencję:

rekurencji http://cart.kolix.de/wp-content/uploads/2009/12/infinite-recursion.jpg

Odpowiedział 04/05/2010 o 17:10
źródło użytkownik

głosy
1

Rekurencja jest kiedy masz operację, która używa się. To prawdopodobnie będzie mieć punkt zatrzymania, w przeciwnym razie będzie to trwać wiecznie.

Powiedzmy, że chcesz wyszukać słowo w słowniku. Masz operację o nazwie „look-up” do Państwa dyspozycji.

Twój przyjaciel mówi: „Mógłbym naprawdę łyżka trochę puddingu teraz!” Nie wiem, o co mu chodzi, więc trzeba spojrzeć w górę „łyżeczką” w słowniku, a to brzmi mniej więcej tak:

Łyżka: rzeczownik - Naczynie z okrągłą kulką na końcu. Łyżka: czasownik - używać łyżkę na coś Łyżka: czasownik - przytulić ściśle od tyłu

Teraz, jako że nie jesteś naprawdę dobry z angielskiego, to wskazuje się w dobrym kierunku, ale trzeba więcej informacji. Więc wybierz „naczynie” i „przytulania” patrzeć na trochę więcej informacji.

Tulić: czasownik - tulić Przybory: rzeczownik - narzędzie, często naczynie jedzenia

Hej! Wiesz co przytulają się, a to nie ma nic wspólnego z budyniem. Wiesz także, że budyń jest coś jesz, więc ma to sens teraz. Twój przyjaciel musi chcieć jeść budyń z łyżką.

Dobra, dobra, to był bardzo chromi przykład, ale ilustruje (może źle) dwóch głównych części rekursji. 1) wykorzystuje się. W tym przykładzie nie zostały naprawdę spojrzał wymownie słowa, aż go zrozumieć, a to może oznaczać, patrząc w górę więcej słów. To prowadzi nas do punktu dwa, 2) zatrzymuje się gdzieś. To musi mieć jakieś podstawy przypadku. W przeciwnym razie, można po prostu skończyć patrząc każde słowo w słowniku, co chyba nie jest zbyt przydatny. Nasza baza-sprawa, że ​​masz wystarczająco dużo informacji, aby połączyć między tym, co było wcześniej i nie rozumieją.

Tradycyjne przykład, który jest podany jest silnia, gdzie 5 jest silnia 1 * 2 * 3 * 4 * 5 (co 120). Przypadek bazowy 0 (lub 1, zależnie). Tak więc, dla dowolnej liczby całkowitej n, to wykonaj następujące czynności

n równe jest 0? powrotu 1 poza tym, powrót N * (silni n-1)

Zróbmy to na przykładzie 4 (co wiemy z wyprzedzeniem jest 1 * 2 * 3 * 4 = 24).

silnia 4 ... to jest 0? No, więc to musi być 4 * silnia 3 ale co silnia 3? to 3 * silnia 2 silnia 2 jest 2 * silnia 1 silnia 1 wynosi 1 * silnia 0 i wiemy silnia 0! :-D to 1, to silnia definicja 1 jest 1 * silnia 0, co było tak ... 1 1 * 1 = 1 silnia 2 jest 2 * silnia 1, która została 1 ... więc 2 * 1 = 2 silnia 3 jest 3 * silnia 2, która została tak 2 ... 3 * 2 = 6 silnia 4 (wreszcie !!) jest 4 * silnia 3, co było 6 ... 4 * 6 24

Silnia to prosta sprawa „przypadku bazowego, i używa się”.

Teraz zauważyć wciąż pracowali nad silni 4 cała droga w dół ... Jeśli chcemy silni 100, musielibyśmy przejść całą drogę w dół do 0 ..., które mogłyby mieć dużo napowietrznych do niego. W ten sam sposób, jeśli znajdziemy niejasne słowo, aby spojrzeć w słowniku, to może wziąć patrząc inne słowa i skanowanie w poszukiwaniu wskazówek kontekstowych, dopóki nie znajdziemy połączenie jesteśmy zaznajomieni. metody rekurencyjne może zająć dużo czasu na pracę swoją drogę. Jednak, gdy są stosowane prawidłowo, i zrozumiał, mogą tworzyć skomplikowane prace zaskakująco prosta.

Odpowiedział 04/05/2010 o 17:04
źródło użytkownik

głosy
1

Bardzo wiele problemów może być rozumiana na dwa rodzaje elementów:

  1. przypadki bazowe, które są podstawowe rzeczy, które można rozwiązać po prostu patrząc na nich, i
  2. Rekurencyjne przypadki, które budują większy problem Spośród mniejsze kawałki (podstawowy lub innych).

Więc co funkcji rekurencyjnej? Dobrze, że tam masz funkcję, która jest zdefiniowana w kategoriach sobie, bezpośrednio lub pośrednio. OK, to brzmi śmiesznie, aż sobie sprawę, że jest to rozsądne za problemy w rodzaju tych opisanych powyżej: można rozwiązać przypadki bazowe bezpośrednio i radzić sobie z rekurencyjnych przypadkach przy użyciu wywołań rekurencyjnych rozwiązać mniejsze kawałki problemu osadzony wewnątrz.

Prawdziwie klasyczny przykład, gdzie trzeba rekursji (lub coś, co pachnie bardzo podobnie do niego) jest wtedy, gdy masz do czynienia z drzewem. Liście drzewa są wariant podstawowy, a gałęzie są rekurencyjne przypadek. (Pseudo-C).

struct Tree {
    int leaf;
    Tree *leftBranch;
    Tree *rightBranch;
};

Najprostszym sposobem drukowania to w porządku jest użycie rekurencji:

function printTreeInOrder(Tree *tree) {
    if (tree->leftBranch) {
        printTreeInOrder(tree->leftBranch);
    }
    print(tree->leaf);
    if (tree->rightBranch) {
        printTreeInOrder(tree->rightBranch);
    }
}

To martwy łatwo zauważyć, że idzie do pracy, ponieważ jest krystalicznie czysta. (Odpowiednik nierekursywnych jest dość dużo bardziej skomplikowane, wymagające strukturę stosu wewnętrznie, aby zarządzać listą rzeczy do przetworzenia). Cóż, zakładając, że nikt nie zrobił okrągły połączenie oczywiście.

Matematycznie trick do pokazując, że rekursji jest oswoić się skupić na znalezieniu metrykę dla rozmiaru argumentów. W naszym przykładzie drzewa, najprostszym metryka jest maksymalna głębokość drzewa poniżej bieżącego węzła. Na liście, to zero. W oddziale pozostawia tylko pod nią, to jeden itp Następnie można po prostu pokazać, że nie jest ściśle uporządkowany ciąg od rozmiaru argumentów, że funkcja wywoływana jest w celu przetworzenia drzewo; argumenty do rozmów rekurencyjnych zawsze są „mniejsze” w sensie metryki niż argument do całkowitego połączenia. Ze ściśle malejącą kardynalnej metryki, jesteś sortowane.

Możliwe jest również, aby mieć nieskończoną rekurencję. To brudny iw wielu językach nie będzie działać, ponieważ stos wysadza. (Gdzie to działa, silnik język musi być ustalenie, że funkcja jakoś nie wraca, a zatem jest w stanie zoptymalizować dala prowadzenia stosu Tricky rzeczy w ogóle;. Tail-rekurencji jest po prostu najbardziej trywialny sposób to zrobić ).

Odpowiedział 04/05/2010 o 16:29
źródło użytkownik

głosy
1

Rekurencja jest technika definiowania funkcji, zestaw lub algorytm pod względem siebie.

Na przykład

n! = n(n-1)(n-2)(n-3)...........*3*2*1

Teraz może być zdefiniowana rekurencyjnie jako: -

n! = n(n-1)!   for n>=1

Pod względem programowania, gdy funkcja lub metoda nazywa się wielokrotnie, aż jakiś szczególny warunek zostanie spełniony, proces ten nazywa Recursion. Ale nie musi być warunkiem zakończeniowy i funkcja lub metoda nie musi wejść w nieskończoną pętlę.

Odpowiedział 04/05/2010 o 16:22
źródło użytkownik

głosy
1

Rekursji do obliczeń jest to technika stosowana do obliczania wyników lub efektów ubocznych po normalnym powrocie z jednej funkcji (metody, procedury lub blok) wywołań.

Rekurencyjne funkcji, z definicji musi mieć możliwość powoływania się bezpośrednio lub pośrednio (za pośrednictwem innych funkcji) uzależnionej od stanu wyjścia lub warunki nie są spełnione. Jeśli warunek jest spełniony wyjście szczególne wezwanie do zwrotu To rozmówcy. Ten proces jest kontynuowany dopóki początkowy wywołania są zwracane z, w którym to czasie żądanego rezultatu lub efektem ubocznym będzie dostępna.

Jako przykład, oto funkcja do wykonywania algorytmu quicksort w Scala ( skopiowany z Wikipedii dla Scala )

def qsort: List[Int] => List[Int] = {
  case Nil => Nil
  case pivot :: tail =>
    val (smaller, rest) = tail.partition(_ < pivot)
    qsort(smaller) ::: pivot :: qsort(rest)
}

W tym przypadku warunek wyjścia jest pusta lista.

Odpowiedział 04/05/2010 o 15:14
źródło użytkownik

głosy
1

Funkcja nazywać się lub wykorzystać swoją własną definicję.

Odpowiedział 04/05/2010 o 14:59
źródło użytkownik

głosy
1

Wszelkie algorytm wykazuje strukturalny rekursji na typ danych, jeśli w zasadzie składa się z przełącznika-oświadczenie o wypadku dla każdego przypadku typu danych.

Na przykład, podczas pracy w danym typie

  tree = null 
       | leaf(value:integer) 
       | node(left: tree, right:tree)

algorytm rekurencyjny strukturalny będzie mieć formę

 function computeSomething(x : tree) =
   if x is null: base case
   if x is leaf: do something with x.value
   if x is node: do something with x.left,
                 do something with x.right,
                 combine the results

to jest naprawdę najbardziej oczywisty sposób pisać żadnych algorith który działa na strukturę danych.

Teraz, jeśli spojrzeć na liczby całkowite (dobrze, że liczby naturalne), jak określono za pomocą aksjomatów Peano

 integer = 0 | succ(integer)

widać, że strukturalny rekurencyjny algorytm na całkowite wygląda następująco

 function computeSomething(x : integer) =
   if x is 0 : base case
   if x is succ(prev) : do something with prev

zbyt dobrze znaną funkcją silnia około najbardziej trywialne przykład formularza.

Odpowiedział 04/05/2010 o 14:53
źródło użytkownik

głosy
1

hej, przepraszam, jeśli moja opinia zgadza się z kimś, jestem po prostu staramy się wyjaśniać rekursji w prostym języku angielskim.

załóżmy, że masz trzy menedżerów - Jack, John Morgan. Jack udaje 2 programistów John - 3, i Morgan - 5. masz zamiar dać każdy menedżer 300 dolarów i chcą wiedzieć, co to będzie kosztować. Odpowiedź jest oczywista - ale co zrobić, jeśli 2 pracowników Morgan-ów są również menedżerowie?

Nadchodzi rekurencji. zacząć od szczytu hierarchii. letni koszt wynosi 0 $. zaczynasz z Jackiem, a następnie sprawdzić, czy ma żadnych menedżerów jak pracowników. jeśli okaże się którykolwiek z nich, należy sprawdzić, czy mają jakieś menedżerów jako pracownicy i tak dalej. Dodaj do 300 $ letni koszt za każdym razem można znaleźć menedżera. Po zakończeniu z Jackiem, przejdź do Jana, jego pracowników, a następnie do Morgan.

Nigdy nie wiadomo, ile cykli pójdziesz przed uzyskaniem odpowiedzi, choć wiesz, ilu menedżerów masz budżet i ile można wydać.

Rekurencja jest drzewem, gałęziami i liśćmi, zwanych odpowiednio rodziców i dzieci. Podczas korzystania z algorytmu rekurencji, mniej lub bardziej świadomie budują drzewo z danymi.

Odpowiedział 04/05/2010 o 13:50
źródło użytkownik

głosy
1

W prostym języku angielskim, rekurencja znaczy znowu i znowu powtórzyć cos.

W programowaniu Przykładem jest wywołanie funkcji w sobie.

Spójrz na poniższy przykład obliczania silni liczby:

public int fact(int n)
{
    if (n==0) return 1;
    else return n*fact(n-1)
}
Odpowiedział 04/05/2010 o 13:48
źródło użytkownik

głosy
1

Rekurencja jest procesem, w którym wywołanie metody iself aby móc wykonać pewne zadanie. Zmniejsza redundency kodu. Większość recurssive funkcje lub metody musi mieć condifiton złamać recussive nazywają to znaczy zatrzymać jej powołanie się jeśli warunek jest spełniony - to zapobiega kreowania nieskończonej pętli. Nie wszystkie funkcje są odpowiednie do stosowania rekurencyjnie.

Odpowiedział 04/05/2010 o 13:42
źródło użytkownik

głosy
1

jego sposób robić rzeczy w kółko, bez końca tak, że każda opcja jest używana.

Na przykład, jeśli chcesz, aby wszystkie linki na stronie html będzie chcesz mieć rekursji bo gdy trzeba uzyskać wszystkie linki na stronie 1 będzie chciał uzyskać wszystkie linki na każdym z linków znajdujących się na pierwszej stronie. Następnie dla każdego linku do NEWPAGE będziemy chcieli te linki i tak dalej ... innymi słowy jest to funkcja, która domaga się od wewnątrz siebie.

kiedy to zrobić potrzebny jest sposób, aby wiedzieć, kiedy przestać, albo będzie w nieskończonej pętli więc dodać całkowitą param do funkcji śledzenia liczby cykli.

wc # trzeba będzie coś takiego:

private void findlinks(string URL, int reccursiveCycleNumb)    {
   if (reccursiveCycleNumb == 0)
        {
            return;
        }

        //recursive action here
        foreach (LinkItem i in LinkFinder.Find(URL))
        {
            //see what links are being caught...
            lblResults.Text += i.Href + "<BR>";

            findlinks(i.Href, reccursiveCycleNumb - 1);
        }

        reccursiveCycleNumb -= reccursiveCycleNumb;
}
Odpowiedział 04/05/2010 o 13:02
źródło użytkownik

głosy
1

„Jeśli mam młotka, aby wszystko wygląda jak gwóźdź”.

Rekurencja to strategia rozwiązywania problemów z ogromnymi problemami, gdzie na każdym kroku tylko „włączyć 2 małe rzeczy w jeden większy rzeczy”, za każdym razem z tym samym młotkiem.

Przykład

Załóżmy, że biurko jest pokryta niezorganizowaną bałagan 1024 dokumentów. Jak zrobić jedno schludne, czyste stos papierów z bałaganu, za pomocą rekurencji?

  1. Podzielić: Rozłóż wszystkie arkusze na zewnątrz, więc trzeba tylko jeden arkusz w każdej „stos”.
  2. Podbić:
    1. Obejść, stawiając każdy arkusz na szczycie jednego innego arkusza. Teraz masz stosy 2.
    2. Obejść, umieszczając każdą 2-stack na drugim 2-stosie. Teraz masz stosy 4.
    3. Obejść, umieszczając każdą 4-stack na drugim 4-stosie. Teraz masz stosy 8.
    4. ... ciągle ...
    5. Teraz masz jeden wielki stos 1024 arkuszy!

Zauważ, że to jest dość intuicyjny, oprócz liczenia wszystkiego (co nie jest bezwzględnie konieczne). Być może nie przejść całą drogę w dół do stosów 1 arkuszy, w rzeczywistości, ale można i to nadal działa. Ważną częścią jest młot: Z twoich ramionach, zawsze można umieścić jeden stos na drugim, aby większy stos, i to nie ma znaczenia (w granicach rozsądku), jak duża jest albo stos.

Odpowiedział 04/05/2010 o 12:54
źródło użytkownik

głosy
1

Rekurencji, ponieważ odnosi się do programowania jest w zasadzie wywoływania funkcji od wewnątrz własnej definicji (wewnątrz siebie), z różnymi parametrami, tak aby wykonać zadanie.

Odpowiedział 04/05/2010 o 12:25
źródło użytkownik

głosy
1

Chcesz używać go w każdej chwili masz strukturę drzewa. Jest to bardzo przydatne w czytaniu XML.

Odpowiedział 21/08/2008 o 14:18
źródło użytkownik

głosy
1

Mario, ja nie rozumiem, dlaczego użyłeś rekursji dla tego przykładu .. Dlaczego po prostu nie pętli każdego wpisu? Coś takiego:

String ArrangeString(TStringList* items, String separator)
{
    String result = items->Strings[0];

    for (int position=1; position < items->count; position++) {
        result += separator + items->Strings[position];
    }

    return result;
}

Powyższa metoda byłoby szybsze i prostsze. Nie ma potrzeby stosowania rekurencji zamiast zwykłej pętli. Myślę, że te rodzaje przykładów dlatego rekurencji dostaje złą reputację. Nawet silnia kanoniczny przykład funkcja jest lepiej realizowane z pętli.

Odpowiedział 06/08/2008 o 04:19
źródło użytkownik

głosy
0

Faktycznie lepiej rekurencyjne rozwiązanie dla silnia powinny być:

int factorial_accumulate(int n, int accum) {
    return (n < 2 ? accum : factorial_accumulate(n - 1, n * accum));
}

int factorial(int n) {
    return factorial_accumulate(n, 1);
}

Ponieważ ta wersja jest Tail Recursive

Odpowiedział 21/08/2008 o 14:39
źródło użytkownik

głosy
0

Używam rekursji. Co to ma wspólnego z posiadające stopień CS ... (co nie, przy okazji)

Typowe zastosowania znalazłem:

  1. Sitemaps - rekursja poprzez plików zaczynając od korzenia dokumentu
  2. pająki - crawling za pośrednictwem strony internetowej, aby znaleźć adres e-mail, linki, etc.
  3. ?
Odpowiedział 06/08/2008 o 04:13
źródło użytkownik

głosy
0

Stworzyłem rekurencyjną funkcję łączenia listę ciągów z separatorem między nimi. Używam go głównie do tworzenia wyrażeń SQL, przekazując listę pól jako „ przedmioty ” i „ przecinek + spacja ” jako separatora. Oto funkcja (wykorzystuje kilka rodzajów Borland Builder rodzimy danych, ale mogą być dostosowane do żadnego innego środowiska):

String ArrangeString(TStringList* items, int position, String separator)
{
  String result;

  result = items->Strings[position];

  if (position <= items->Count)
    result += separator + ArrangeString(items, position + 1, separator);

  return result;
}

Ja nazywam to w ten sposób:

String columnsList;
columnsList = ArrangeString(columns, 0, ", ");

Wyobraź sobie, że masz tablicę o nazwie „ pola ” z tych danych wewnątrz niego: „ ALBUMNAME ”, „ RELEASEDATE ”, „ labelId ”. Następnie należy wywołać funkcję:

ArrangeString(fields, 0, ", ");

Jako funkcja zacznie działać, zmienna „ wynik ” otrzymuje wartość pozycji 0 tablicy, która jest „ ALBUMNAME ”.

Następnie sprawdza, czy pozycja to do czynienia z jest ostatni. Ponieważ nie jest to Łączy wynik z separatorem i wynik funkcji, co Boże, czy to ta sama funkcja. Ale tym razem, to sprawdzić, to nazywają się dodając 1 do pozycji.

ArrangeString(fields, 1, ", ");

To powtarza, tworząc stos LIFO, aż osiągnie punkt, w którym pozycja jest rozpatrywane jest ostatni, więc funkcja zwraca tylko przedmiot na tej pozycji na liście, nie łącząc więcej. Następnie stos jest łączony do tyłu.

Rozumiem? Jeśli nie mam innego sposobu, aby ją wyjaśnić. : O)

Odpowiedział 06/08/2008 o 04:00
źródło użytkownik

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more