Mi rekurzió és mikor kell használni?

szavazat
121

Az egyik téma, hogy úgy tűnik, hogy jöjjön fel rendszeresen levelezőlisták és online viták az érdemi (vagy annak hiánya) csinál egy Computer Science fokozat. Egy érv, hogy úgy tűnik, hogy jöjjön fel újra és újra a negatív felet, hogy már kódoló néhány néhány év, és még soha nem használt rekurziót.

A kérdés tehát:

  1. Mi rekurzió?
  2. Mikor fogok én használni rekurzió?
  3. Miért nem használják az emberek a rekurzió?
A kérdést 06/08/2008 03:29
a forrás felhasználó
Más nyelveken...                            


40 válasz

szavazat
86

Van néhány jó magyarázatot rekurzió ebben a téma, ez a válasz, hogy miért ne használja ezt a legtöbb nyelven. * A legtöbb nagy elengedhetetlen nyelvi implementációk (azaz minden nagyobb végrehajtását C, C ++, Basic, Python Ruby, a Java és C #) iterációs mérhetetlenül előnyösebb rekurziót.

Ahhoz, hogy megértsük, miért, séta a lépéseket, amelyek a fenti nyelvek használni, hogy hívja a funkció:

  1. tér faragott ki a verem a függvény argumentumok
  2. A funkció érveit másolja be ez az új hely
  3. szabályozás ugrik a függvény
  4. A függvény kódja fut
  5. A függvény eredménye bemásolja a visszatérési érték
  6. a verem visszacsévél korábbi álláspontját
  7. ellenőrzési ugrik vissza, ahol a függvény hívták

Doing mindezen lépések időt vesz igénybe, általában egy kicsit több, mint tart végighaladni egy hurok. Azonban az igazi probléma az 1. lépésben. Ha sok program indul el, úgy kiosztani egy darab memória a verem, és amikor elfogy a memória, hogy (gyakran, de nem mindig a rekurzió), a program összeomlik miatt verem túlcsordulás .

Így ezeken a nyelveken rekurzió lassabb, és azt teszi, akkor sebezhető összeomlik. Vannak még érveket használ, hogy mégis. Általában írt kód rekurzív rövidebb és egy kicsit elegánsabb, ha tudod, hogyan kell olvasni.

Van egy technika, hogy a nyelv megvalósítói is használnak úgynevezett farok hívás optimalizálás amely megszünteti bizonyos csoportjai verem túlcsordulás. Tedd tömören: ha egy függvény visszatérési kifejezés egyszerűen az eredménye egy függvényhívás, akkor nem kell, hogy egy új szintre a verembe, akkor újra az aktuális a hívott függvénynek. Sajnálatos módon néhány elengedhetetlen nyelvi implementáció farok hívás optimalizálás épült.

* Szeretem a rekurziót. A kedvenc statikus nyelv nem használ hurkok egyáltalán, rekurzió az egyetlen módja, hogy tegyen valamit többször. Csak nem gondolja, hogy a rekurzió általában jó ötlet nyelvek, amelyek nem hangolt rá.

** Apropó Mario, a tipikus nevet a ArrangeString funkció „csatlakozni”, és meg lennék lepve, ha a választott nyelven még nem rendelkezik végrehajtási belőle.

Válaszolt 06/08/2008 06:09
a forrás felhasználó

szavazat
63

Egyszerű angol példát rekurziót.

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.
Válaszolt 04/05/2010 17:38
a forrás felhasználó

szavazat
49

A legalapvetőbb számítástechnikai értelemben rekurzió egy olyan funkció, amely magát. Tegyük fel, hogy van egy láncolt lista szerkezete:

struct Node {
    Node* next;
};

És azt akarja, hogy megtudja, milyen hosszú egy kapcsolt lista, akkor ezt a rekurzió:

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

(Ez persze lehet tenni egy hurok is, de hasznos, mint egy illusztráció a fogalom)

Válaszolt 04/05/2010 12:25
a forrás felhasználó

szavazat
46

Amikor egy függvény önmagát hívja meg, ami egy hurok, akkor ez a rekurzió. Mint bármi, vannak jó és rossz célokra felhasználási rekurziót.

A legegyszerűbb példa a farok rekurzió, ahol az utolsó sorban a funkció egy hívást, hogy maga:

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

Ez azonban egy sánta, szinte értelmetlen például azért, mert könnyen helyettesíthető hatékonyabb iteráció. Végtére is, a rekurzió szenved függvényhívás fölött, amely a fenti példában jelentősek lehetnek, mint a művelet a függvény belsejében is.

Tehát az egész oka, hogy nem rekurzió helyett iteráció kell lennie, hogy kihasználják a hívási verem , hogy néhány okos dolog. Például, ha hívja a funkciót többször, különböző paraméterek belül ugyanabban a körben, akkor ez a módja annak, hogy elágazás . A klasszikus példa a Sierpinski háromszög .

írja kép leírása itt

Tudod felhívni egyike azon nagyon egyszerűen rekurzió, ahol a hívási verem ágak 3 irányban:

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);
    }
}

Ha megpróbálja ugyanezt csinálja iterációs Szerintem találsz tart sokkal több kódot elérni.

Egyéb gyakori használati esetek lehetnek áthaladó hierarchiák, pl website csúszómászó, könyvtár összehasonlítások stb

Következtetés

Gyakorlati szempontból a rekurzió a legésszerűbb, amikor szüksége van iteratív elágazást.

Válaszolt 04/05/2010 14:33
a forrás felhasználó

szavazat
28

A rekurzió egy olyan módszer, problémamegoldás alapuló oszd meg és uralkodj mentalitás. Az alapötlet az, hogy vegye meg az eredeti problémát, és osszuk kisebb (könnyebben megoldható) esetekben önmagában megoldja a kisebb példányok (általában ugyanazt az algoritmust újra), majd szerelje őket a végső megoldást.

A kanonikus példa egy rutin, hogy létrehoz a Faktoriális n. Faktoriális n szorzata összes szám 1 és n között. Iteratív megoldás C # néz ki:

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

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

  return fact;
}

Nincs semmi meglepő iteratív megoldás, és ez kell, hogy értelme, hogy bárki ismeri a C #.

A rekurzív oldatot találtuk annak elismerését, hogy az n-edik Faktoriális n * Tény (n-1). Vagy másképp fogalmazva, ha tudjuk, hogy mi az adott Factorial szám lehet számítani a következő egy. Itt látható a rekurzív megoldás C #:

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

  return n * FactRec( n - 1 );
}

Az első része ez a funkciója nem ismert, mint egy alapeset (vagy néha Guard szakasz), és az, ami megakadályozza az algoritmus futásának örökre. Csak vissza az 1-es érték, ha a függvény hívására értéke 1 vagy annál kevesebb. A második rész sokkal érdekesebb, és az úgynevezett rekurzív lépés . Itt hívjuk ugyanazt a módszert egy kissé módosított paraméter (mi csökkentse az 1), majd szorozzuk meg az eredményt a mi példányát n.

Amikor először találkozott ez lehet a fajta zavaró így tanulságos megvizsgálni, hogyan működik, ha fut. Képzeljük el, hogy hívjuk FactRec (5). Mi adja meg a rutin, nem vette fel a bázis esetében, és így a végén, mint ez:

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

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

Ha újra be a módszert a 4. paraméter vagyunk megint nem állítja le az őr záradékot és így a végén itt:

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

Ha helyettesíteni ezt visszatérési értéke a visszatérési érték felett érünk

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

Ez ad egy nyom, hogy milyen a végső megoldás megérkezett így fogunk gyorsított, és mutassa minden egyes lépés az úton lefelé:

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

Ez végső helyettesítés történik, amikor a bázis esetében aktiválódik. Ezen a ponton van egy egyszerű képlet algrebraic megoldani, amely megegyezik közvetlenül a meghatározása faktoriális az első helyen.

Ez tanulságos megjegyezni, hogy minden hívás a módszer eredménye akár egy alapeset váltunk, vagy egy hívás, hogy ugyanazt a módszert, ahol a paraméterek közelebb egy alapeset (gyakran nevezik a rekurzív hívás). Ha ez nem így van, akkor a módszer fog futni örökké.

Válaszolt 06/08/2008 03:54
a forrás felhasználó

szavazat
12

A rekurzió egy probléma megoldása egy olyan funkcióval, amely magát. Jó példa erre egy faktoriális függvény. Faktoriális egy matematikai probléma, ahol a faktoriális 5, például, 5 * 4 * 3 * 2 * 1 Ez a funkció megoldja ezt a C # a pozitív egészek (nem vizsgált - előfordulhat, hogy egy hiba).

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

    return n * Factorial(n - 1);
}
Válaszolt 04/05/2010 12:29
a forrás felhasználó

szavazat
9

Vegyünk egy régi, jól ismert probléma :

A matematika, a legnagyobb közös osztó (lnko) ... két vagy több nullától egészek, a legnagyobb pozitív egész szám, amely elválasztja a számokat maradék nélkül.

A meghatározás az lnko meglepően egyszerű:

lnko meghatározás

ahol mod a modulo operátor (azaz, a fennmaradó után osztás).

Az angol, ez a meghatározás szerint a legnagyobb közös osztó bármilyen számú és nulla ez a szám, és a legnagyobb közös osztó két szám m és n a legnagyobb közös osztó n , és a maradék után elosztjuk m a n .

Ha szeretné tudni, hogy ez miért működik, lásd a Wikipedia a euklideszi algoritmus .

Nézzük kiszámítja lnko (10, 8) példaként. Minden lépés megegyezik az egyik éppen előtte:

  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

Az első lépésben, 8 nem egyenlő nulla, így a második része a meghatározás érvényes. 10 mod 8 = 2, mert 8 bemegy 10 egyszer a fennmaradó 2. lépésben 3, a második rész vonatkozik újra, de ez alkalommal 8 mod 2 = 0, mert 2 oszt 8 nincs maradék. Az 5. lépésben a második argumentum 0, így a válasz 2.

Észrevetted, hogy lnko megjelenik mind a bal és jobb oldalán egyenlőségjel? A matematikus azt mondaná, ez a meghatározás rekurzív, mert a kifejezés maga meghatározó ismétlődik benne a meghatározása.

Rekurzív definíciók általában elegáns. Például egy rekurzív definíció az összeg a lista

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

ahol headaz első elem egy listában, és taila többi a listán. Vegye figyelembe, hogy sumvisszatér belül annak meghatározása a végén.

Talán inkább a maximális értéket adja eredményül helyett:

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

Lehet, hogy meghatározzák szaporodása nem negatív egész rekurzív, hogy átalakítsuk azt egy sor kiegészítésekkel:

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

Ha ez kicsit átalakítja a szorzás egy sorozat kiegészítések nincs értelme, próbálja kiterjeszteni néhány egyszerű példát, hogy hogyan működik.

Merge sort egy szép rekurzív definíció:

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

Rekurzív definíciók körül, ha tudod, mit kell keresni. Figyeljük meg, hogy az összes ilyen meghatározások nagyon egyszerű alap esetben például , lnko (m, 0) = m. A rekurzív esetben megnyirbál meg a problémát, hogy le a könnyű válaszokat.

Ezzel a megértés, akkor most értékelik a többi algoritmusok Wikipedia cikket rekurzív !

Válaszolt 04/05/2010 14:58
a forrás felhasználó

szavazat
9

A rekurzió egy olyan eljárás, amely megoldja a problémát megoldjuk egy kisebb változata a problémát, és akkor használja ezt az eredményt, valamint néhány más számítás megfogalmazni a választ, hogy az eredeti probléma. Gyakran előfordul, hogy a folyamat megoldása a kisebb változat, a módszer megoldja a még kisebb változata a problémát, és így tovább, amíg el nem éri a „alapeset”, ami triviális megoldani.

Például kiszámításához faktoriális számát X, lehet képviselni azt X times the factorial of X-1. Így a módszer „recurses”, hogy megtalálják a faktoriális X-1, majd megszorozza bármi is van a X, hogy a végső választ. Persze, hogy megtalálják a faktoriális X-1, akkor az először kiszámítja a faktoriális X-2, és így tovább. A bázis az esetben lenne, ha Xértéke 0 vagy 1, amely esetben tudja, hogy visszatérjen 1, mivel 0! = 1! = 1.

Válaszolt 04/05/2010 12:26
a forrás felhasználó

szavazat
9
  1. Egy függvény, amely magát
  2. Ha a funkció lehet (könnyen) bontjuk Egyszerű működés és ugyanazt a funkciót még kisebb része a problémát. Azt kell mondanom, inkább, hogy ez teszi egy jó jelölt rekurziót.
  3. Ők csinálják!

A kanonikus példa a faktoriális, amely így néz ki:

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

  return a*fact(a-1);
}

Általában rekurzió nem feltétlenül gyors (függvényhívás overhead általában magas, mert rekurzív függvények általában kicsi, lásd fent), és szenved valamilyen probléma (veremtúlcsordulás valaki?). Egyesek azt mondják, hogy általában nehéz, hogy „jog” nem-triviális esetek, de én nem igazán vásárolnak bele. Bizonyos helyzetekben a rekurzió a legésszerűbb és a legelegánsabb és egyértelmű módon, hogy írjon egy adott funkciót. Meg kell jegyezni, hogy egyes nyelvek előnyben rekurzív megoldást, és optimalizálja azok sokkal (LISP jut eszembe).

Válaszolt 06/08/2008 03:35
a forrás felhasználó

szavazat
7

A rekurzív függvényt, amely saját magát hívja meg. A leggyakoribb ok, amit találtam, hogy használni végighalad a fa szerkezet. Például, ha van egy TreeView jelölőnégyzeteket (gondolom telepítés egy új program, „választani a telepítendő szolgáltatásokat” oldal), azt érdemes a „összes kijelölése” gombra, ami valahogy így néz ki (pszeudokódját):

function cmdCheckAllClick {
    checkRecursively(TreeView1.RootNode);
}

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

Tehát láthatjuk, hogy az első checkRecursively ellenőrzi a csomópont amelyen át, majd felhívja magára az egyes adott csomópont gyermekeit.

Önnek nem kell, hogy egy kicsit óvatos rekurziót. Ha kap egy végtelen rekurzív hurok, akkor kap egy kötegtúlcsordulást kivétel :)

Nem tudok egy ok, amiért az emberek nem használják, ha szükséges. Ez akkor hasznos, bizonyos körülmények között, míg másokban nem.

Azt hiszem, hogy azért, mert ez egy érdekes technikát, néhány kódolók talán a végén használja gyakrabban, mint kellene, anélkül, hogy valóban igazolható. Ez adta a rekurzió egy rossz név bizonyos körökben.

Válaszolt 06/08/2008 03:44
a forrás felhasználó

szavazat
5

Rekurzió egy kifejezés közvetlenül vagy közvetve hivatkozó magát.

Tekintsük rekurzív betűszavak, mint egy egyszerű példa:

  • GNU jelentése GNU Nem Unix
  • PHP jelentése PHP: Hypertext Preprocessor
  • YAML jelentése YAML Nem jelölőnyelv
  • BOR jelentése Wine nem egy emulátor
  • VISA jelentése Visa International Service Association

További példák a Wikipedia

Válaszolt 04/05/2010 12:56
a forrás felhasználó

szavazat
5

Itt egy egyszerű példa: hány elem a készlet. (Vannak jobb módszerek számolni a dolgokat, de ez egy szép egyszerű rekurzív példa.)

Először is, szükségünk két szabály:

  1. Ha a készüléket üres, az elemek számát a beállított nulla (duh!).
  2. ha a halmaz nem üres, a gróf egyik plusz a tételek számát a beállított után egy elemet el kell távolítani.

Tegyük fel, hogy van egy sor, mint ez: [xxx]. nézzük hány példány van.

  1. a készlet [xxx], amely nem üres, ezért alkalmazzák szabály 2. A tételek száma egy plusz elemek számát a [xx] (azaz mi eltávolított egy elemet).
  2. a készlet [xx], ezért alkalmazzák 2. szabály újra: egy + elemek számát [x].
  3. a készlet [x], amely még mindig egyezik 2. szabály: egy + elemek számát [].
  4. Most a készlet [], amely megfelel az 1. szabály: a szám nulla!
  5. Most, hogy tudjuk a választ a 4. lépésben (0), meg tudjuk oldani a 3. lépés (1 + 0)
  6. Hasonlóképpen, most, hogy tudjuk a választ a 3. lépésben (1), meg tudjuk oldani a 2. lépés (1 + 1)
  7. És végül most, hogy tudjuk a választ a 2. lépésben (2), meg tudjuk oldani 1. lépés (1 + 2), és kap a száma db [xxx], amely 3. Hurrá!

Mi is képviseli ezt:

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

Alkalmazása során a rekurzív megoldás, akkor általában legalább 2 szabályok:

  • alapján, az egyszerű eset, amely kimondja, hogy mi történik, ha már „használt fel” az összes adatot. Ez általában néhány variáció „ha végre az adatok feldolgozására, a válasz X”
  • A rekurzív szabály, amely kimondja, hogy mi történik, ha még van adat. Ez általában valamilyen szabály, amely azt mondja: „tenni valamit, hogy az adathalmaz kisebb, és újra a szabályokat, hogy a kisebb adathalmaz.”

Ha lefordítani a fenti pszeudokódokra, megkapjuk:

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

Van egy sokkal hasznosabb példák (bejárja a fát, például), ami biztos vagyok benne, mások fedezi.

Válaszolt 06/08/2008 04:12
a forrás felhasználó

szavazat
5

A rekurzió akkor működik a legjobban, amit szeretek hívni „fraktál problémák”, ahol van dolgunk, nagy dolog, hogy készült a kisebb változatai, hogy nagy dolog, amelyek mindegyike egy még kisebb változata a nagy dolog, és így tovább. Ha valaha is áthalad, vagy keresni valamit, mint egy fa, vagy beágyazott azonos struktúrák, van egy probléma, hogy lehet egy jó jelölt rekurziót.

Emberek ne rekurzív több okból:

  1. A legtöbb ember (magamat is beleértve) vágja a programozást fogak eljárási vagy objektumorientált programozás, szemben a funkcionális programozás. Ahhoz, hogy az ilyen emberek, az iteratív megközelítés (jellemzően hurok) úgy érzi, sokkal természetesebb.

  2. Azok közülünk, akik csökkenteni a programozás fogak eljárási vagy objektumorientált programozási gyakran mondták, hogy elkerülje a rekurziót, mert hajlamos a hibákra.

  3. Mi gyakran mondták, hogy a rekurzió lassú. Hívó és visszatérő rutin többször jár a sok halom rámenős és popping, ami lassabb, mint hurok. Azt hiszem, néhány nyelv kezelni ezt jobban, mint mások, és ezek a nyelvek nagy valószínűséggel nem azok, ahol az uralkodó paradigma eljárási vagy objektumorientált.

  4. Legalább egy pár programozási nyelvek, amit használnak, Emlékszem tárgyaláson ajánlások nem használja rekurzió ha nem lesz túl egy bizonyos mélységet, mert a verem nem olyan mély.

Válaszolt 06/08/2008 04:12
a forrás felhasználó

szavazat
4

1.) Eljárás rekurzív, ha ez nevezi magát; vagy közvetlenül:

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

vagy közvetve:

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

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

2.) Ha használni rekurzió

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.) Az emberek rekurzió csak akkor, ha nagyon bonyolult, hogy írjon iteratív kódot. Például, fa bejárás technikák, mint előrendelhető, postorder lehet tenni mind iteratív és rekurzív. De általában használjuk rekurzív az egyszerűsége miatt.

Válaszolt 11/03/2014 10:47
a forrás felhasználó

szavazat
4

A rekurzív állítás, amelyben megadhatja a folyamat, hogy mit kell tennie a következő kombinációjaként a be- és amit eddig tettünk.

Például, hogy faktoriális:

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

De ez könnyen belátható faktoros (6) is van:

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

Tehát általában:

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

Természetesen az a baj, rekurzió, hogy ha azt akarjuk, hogy meghatározza a dolgokat tekintve, amit már megtette, ott kell lennie valahol kezdeni.

Ebben a példában, csak hogy egy különleges eset meghatározásával faktoros (1) = 1.

Most azt látjuk, hogy az alulról felfelé:

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

Mivel meghatározott faktoriális (1) = 1, akkor éri el a „lefelé”.

Általánosságban elmondható, hogy a rekurzív eljárások két részből állnak:

1) A rekurzív része, amely meghatározza valamilyen eljárással szempontjából új bemenet kombinált amit „már kész” ugyanezzel az eljárással. (azaz factorial(n) = n*factorial(n-1))

2) A alaprész, amely gondoskodik arról, hogy az eljárás nem ismétlődik örökké azáltal, hogy néhány helyen kezdeni (pl factorial(1) = 1)

Ez lehet egy kicsit zavaró, hogy a fejed körül először, de csak nézd meg egy csomó példát, és azt kell minden jön össze. Ha szeretne egy mélyebb megértését, a koncepció, tanulmány matematikai indukció. Továbbá, ne feledje, hogy egyes nyelvek optimalizálni rekurzív hívások, míg mások nem. Ez elég egyszerű, hogy őrülten lassú rekurzív függvények, ha nem vigyázunk, de ott is technikákat, hogy azok eredményes, a legtöbb esetben.

Remélem ez segít...

Válaszolt 04/05/2010 14:30
a forrás felhasználó

szavazat
4

Szeretem ezt a definíciót:
A rekurzió, a rutin megoldja egy kis része a probléma maga osztja a probléma kisebb darabokra, majd saját magát hívja, hogy megoldja az egyes kisebb darabokra.

Én is, mint Steve McConnells vita rekurzió teljes kód, ahol azt rója a példák in Computer Science könyvek rekurzió.

Ne használja rekurzív faktoriális vagy Fibonacci számok

Az egyik probléma a számítógéppel tudomány tankönyvek az, hogy bemutassa buta példát rekurziót. A tipikus példák számítási faktoriális vagy számítástechnikai Fibonacci szekvenciát. A rekurzió egy hatékony eszköz, és ez nagyon buta használni sem az az eset. Ha egy programozó, aki dolgozott nekem használt rekurzív számítani a faktoriális, én bérel valaki mást.

Azt hittem, ez egy nagyon érdekes pont emelni, és lehet az oka annak, rekurzív gyakran félreértik.

EDIT: Ez nem volt egy dig Dav válasza - nem láttam volna, hogy a válasz, amikor közzétette ezt

Válaszolt 04/05/2010 12:29
a forrás felhasználó

szavazat
3

Egy példa: Egy rekurzív definíció egy lépcső: Egy lépcső áll: - egy lépésben, és egy lépcső (rekurzív) -, vagy csak egyetlen lépésben (terminációs)

Válaszolt 04/05/2010 14:34
a forrás felhasználó

szavazat
3

Nos, ez egy elég tisztességes meghatározása van. És wikipedia egy jó definíció is. Úgyhogy egy újabb (valószínűleg rosszabb) meghatározása az Ön számára.

Amikor az emberek lásd „rekurzió”, ők általában beszélünk függvényében, hogy már írt, amely felhívja magára többször, amíg meg nem történik a munkáját. A rekurzió hasznos lehet, ha áthaladó hierarchiák adatszerkezeteket.

Válaszolt 04/05/2010 12:27
a forrás felhasználó

szavazat
3

Ahhoz recurse egy megoldott probléma: nem tesz semmit, akkor kész.
Ahhoz recurse egy nyitott probléma: nem a következő lépés, majd recurse a többit.

Válaszolt 06/08/2008 04:32
a forrás felhasználó

szavazat
2

Ez egy régi kérdés, de szeretnék hozzáadni válaszát logisztikai szempontból (vagyis nem algoritmus helyességét szempontból, illetve teljesítmény szempontjából).

ÉN használ Java munkát, és a Java nem támogatja a beágyazott függvény. Mint ilyen, ha azt akarom, hogy a rekurzió, talán meg kell határoznunk egy külső funkció (amely csak azért, mert a kód dudorok ellen Java bürokratikus szabály), vagy talán még az refactor a kódot összesen (ami nagyon utálom csinálni).

Így sokszor elkerülhető rekurzió, és használata verem működés helyett, mert rekurzív maga lényegében egy halom műveletet.

Válaszolt 30/08/2014 11:09
a forrás felhasználó

szavazat
2

A rekurzív függvény olyan függvény, amely tartalmazza a hívás is. A rekurzív struct egy struct, amely tartalmaz egy példánya is. Akkor össze a két, mint egy rekurzív osztály. A legfontosabb része egy rekurzív tétel az, hogy tartalmaz egy példánya / call önmagában.

Vegyünk két tükör egymással szemben. Láttuk az ügyes végtelenbe hatást teszik. Minden reflexió egy példánya egy tükör, amely belül van egy további példánya tükör, stb A tükör tartalmazó tükrözi önmagában rekurzió.

A bináris keresési fa jó programozási példát rekurziót. A szerkezet rekurzív, és minden csomópont tartalmaz 2 esetekben egy csomópont. Funkciók dolgozni bináris kereső fába is rekurzív.

Válaszolt 04/05/2010 17:46
a forrás felhasználó

szavazat
2

Közérthető nyelven: Tegyük fel, meg tudod csinálni 3 dolog:

  1. Vegyünk egy alma
  2. Írja le tally jelek
  3. Gróf tally jelek

Van egy csomó almát előtted az asztalon, és szeretné tudni, hogy hány alma van.

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

A folyamat megismételve ugyanazt a dolgot, amíg meg nem történik az úgynevezett rekurzív.

Remélem, hogy ez a „sima angol” válasz, amit keres!

Válaszolt 04/05/2010 14:09
a forrás felhasználó

szavazat
1

A legegyszerűbb definíciója rekurzió „self-hivatkozás”. A funkció, amely utal a maga, tehát nevezi magát rekurzív. A legfontosabb dolog, hogy tartsa szem előtt, hogy egy rekurzív függvényt kell a „alapeset”, azaz olyan állapot, amely ha igaz okozza azt, hogy ne hívja magát, és így megszünteti a rekurziót. Ellenkező esetben akkor végtelen ciklus:

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

Válaszolt 04/05/2010 17:10
a forrás felhasználó

szavazat
1

A rekurzió az, amikor van egy művelet, amely önmagát. Valószínűleg lesz egy megállási pont, különben nem fog menni a végtelenségig.

Tegyük fel, hogy azt szeretné, hogy néz ki egy szót a szótárban. Van egy műveletet a „look-up” az Ön rendelkezésére.

A barát azt mondja: „Én tényleg kanál egy kis pudingot most!” Nem tudom, mit jelent, így néz ki: „kanál” a szótárban, és azt olvassa, valahogy így:

Spoon: főnév - egy eszköz, kerek gombóc a végén. Spoon: ige -, hogy egy kanál valami kanál: ige - átölel szorosan hátulról

Most, az, hogy te tényleg nem jó az angol, ez arra mutat, akkor a helyes irányba, de ha szükség van további információra. Tehát, ha a „eszköz” és „ölelkezés”, hogy néz ki még néhány információt.

Ölelés: ige - odabújik Utensil: főnév - egy eszköz, gyakran evőszerszám

Hé! Tudod mit snuggling van, és ennek semmi köze a pudingot. Azt is tudjuk, hogy a puding az, amit eszik, így van értelme most. A barátod meg akarja enni puding egy kanállal.

Oké, oké, ez egy nagyon béna példa, de jól illusztrálja (talán rosszul) a két fő részből rekurzió. 1) maga is él. Ebben a példában, akkor nem igazán látszott egy szót jelentőségteljesen amíg meg nem érti meg, és ez azt jelentheti, felnézett több szót. Ez elvezet minket a pont két, 2), megáll valahol. Azt, hogy van valamilyen alapeset. Ellenkező esetben, ha azt csak a végén keresi fel minden szót a szótárban, ami valószínűleg nem túl hasznos. A alapeset volt, hogy van elég információ, hogy a kapcsolat aközött, amit korábban nem, és nem értettem.

A hagyományos például, hogy ez adott van faktoriális, ahol az 5 faktoriális jelentése 1 * 2 * 3 * 4 * 5 (ami 120). A bázis az esetben lenne 0 (vagy 1, attól függően). Tehát, bármilyen egész szám n, akkor tegye a következőket

jelentése n értéke 0? vissza 1 egyébként, vissza n * (faktoriális n-1)

csináljuk példáján 4 (amiről tudjuk, idő előtt 1 * 2 * 3 * 4 = 24).

faktoriális 4 ... ez 0? nem, ezért kell a 4 * faktoriálisát 3, de mi faktoriálisát 3? ez a 3 * faktoros 2 faktoriális 2 2 * faktoriálisát 1 faktoros 1 1 * faktoriálisát 0 és tudjuk faktoriálisát 0! :-D ez 1, ez a definíciója faktoriálisát 1 jelentése 1 * faktoriálisát 0, ami 1 ... így 1 * 1 = 1 faktoriális 2 2 * faktoriális 1 volt, ami 1 ... így 2 * 1 = 2 faktoriális 3 3 * faktoriális 2 volt, ami 2 ... így 3 * 2 = 6 faktoriális 4 (végre !!) 4 * faktoriális 3 volt, ami 6 ... 4 * 6 jelentése 24

Factorial egy egyszerű eset a „alapeset, és maga is él.”

Most észre azt még dolgoznak faktoriálisát 4 egész úton lefelé ... Ha akartuk faktoros 100, mi volna menni egészen 0 ... ami lehet, hogy egy csomó fölött rá. Ugyanilyen módon, ha találunk egy olyan homályos szó, hogy néz ki a szótárban is eltarthat keresi fel más szavakkal és beolvasás összefüggésben nyomokat, amíg nem találunk egy kapcsolatot vagyunk tisztában. Rekurzív eljárások hosszú időt vesz igénybe, hogy a munka az utat. Azonban, ha ők használják helyesen, és megértette, hogy lehet, hogy bonyolult munka meglepően egyszerű.

Válaszolt 04/05/2010 17:04
a forrás felhasználó

szavazat
1

Nagyon sok problémát lehet úgy két típusú darab:

  1. Base esetben, amelyek elemi dolog, hogy meg lehet oldani, hogy csak nézte őket, és
  2. Rekurzív esetek, melyek építeni egy nagyobb probléma ki kisebb darabokra (elemi vagy más módon).

Tehát mi az a rekurzív függvény? Nos, ez az, ahol van egy funkció, amely meghatározott feltételek is, közvetlenül vagy közvetve. OK, hogy nevetségesen hangzik, amíg rájössz, hogy van értelme a problémák a fentiekben leírt: megoldani az alap esetben közvetlenül és foglalkozik a rekurzív esetek segítségével rekurzív hívások, hogy megoldja a kisebb darabokra a probléma ágyazva.

Az igazán klasszikus példája, ahol szükség van a rekurzió (vagy valami illata nagyon tetszik), amikor van dolgunk, egy fát. A levelek a fa az alapeset, és az ágak a rekurzív ügyben. (A pszeudo-C.)

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

A legegyszerűbb módja a nyomtatás ezt meg annak érdekében, hogy használja a rekurzió:

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

Ez halott könnyű belátni, hogy ez működni fog, mivel ez kristálytiszta. (A nem-rekurzív egyenértékű elég sok bonyolultabb igénylő verem szerkezet belsőleg kezelni a listát, hogy mit feldolgozni.) Nos, feltételezve, hogy senki sem tett egy kör alakú kapcsolat természetesen.

Matematikailag a trükk, hogy azt mutatja, hogy a rekurzió megszelidítve összpontosítani találni egy mutatót a mérete az érveket. A mi fán például a legegyszerűbb mutató a maximális mélysége a fa alatt a jelenlegi csomópontot. Abban levelek, az nulla. Egy ág csak a levelek alatta, ez az egyik, stb, akkor egyszerűen azt mutatják, hogy ez szigorúan előírt sorrendben a mérete az érveket, amelyek a funkció indul el annak érdekében, hogy feldolgozza a fa; az érveket, hogy a rekurzív hívások mindig „kisebb” abban az értelemben, a mutató, mint az az érv, hogy az általános hívást. A szigorúan csökkenő bíboros mutató, akkor rendezve.

Az is lehetséges, hogy egy végtelen ciklus. Ez rendetlen és sok nyelven nem fog működni, mert a verem felrobban. (Ha ez működik, a nyelvi motort kell annak megállapítására, hogy a funkció valahogy nem tér vissza, és ezért képes optimalizálni el a vezetését a verem. Tricky dolgok általában; farok rekurzió csak a legtriviálisabb módja ennek .)

Válaszolt 04/05/2010 16:29
a forrás felhasználó

szavazat
1

Rekurzió technika meghatározásának függvényében, egy sor vagy egy algoritmus szempontjából is.

Például

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

Most lehet meghatározni rekurzívan: -

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

A programozás szempontjából, amikor egy függvény vagy metódus nevezi magát többször, amíg egy adott feltétel lesz elégedett, ezt a folyamatot nevezik rekurzió. De ott kell lennie egy lezáró állapot és működés vagy módszert kell semmilyen lép végtelen ciklusba.

Válaszolt 04/05/2010 16:22
a forrás felhasználó

szavazat
1

Rekurzió computing egy technikát alkalmazzuk, hogy kiszámítsuk az eredmény vagy a mellékhatás követően a rendes hozamnak egyetlen funkciót (módszer, eljárás vagy blokk) hívással.

A rekurzív függvény, definíció szerint kell a képességét, hogy hivatkozhat önmagában közvetlenül vagy közvetve (egyéb funkciók) függően egy kilépési feltétel vagy feltételek nem teljesülnek. Ha egy kilépési feltétel teljesül az adott hívási visszatér ez a hívónak. Ez addig folytatódik, amíg a kezdeti hívási visszaadott, ekkor a kívánt eredményt, vagy mellékhatása lesz elérhető.

Példaként itt van egy funkció elvégzésére Quicksort algoritmus Scala ( átmásolja a Wikipedia bejegyzés Scala )

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

Ebben az esetben a kilépési feltétel egy üres lista.

Válaszolt 04/05/2010 15:14
a forrás felhasználó

szavazat
1

függvényhívás maga, vagy használja a saját meghatározását.

Válaszolt 04/05/2010 14:59
a forrás felhasználó

szavazat
1

Bármilyen algoritmus mutat szerkezeti rekurzió egy adattípust, ha lényegében egy switch-nyilatkozatot az ügyben minden esetben az adattípus.

például ha dolgozik egy típus

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

szerkezeti rekurzív algoritmus lenne a forma

 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

ez valóban a legkézenfekvőbb módja, hogy írjon olyan algoritmussal, ami működik adatszerkezet.

Most, amikor megnézi az egész (na jó, a természetes számok) használatával definiált Peano axiómák

 integer = 0 | succ(integer)

látod, hogy a szerkezeti rekurzív algoritmus egész úgy néz ki, mint ez

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

A túl-jól ismert faktoriális függvény a leginkább triviális példát ebben a formában.

Válaszolt 04/05/2010 14:53
a forrás felhasználó

szavazat
1

hé, sajnálom, ha véleményem egyetért valaki, csak próbálom elmagyarázni rekurzió egyszerű angol nyelven.

Tegyük fel, hogy van három vezetők - Jack, John Morgan. Jack felszabadítással 2 programozók, John - 3, és a Morgan - 5. fogsz adni minden vezető 300 $, és szeretné tudni, mi kerülne. A válasz nyilvánvaló -, de mi van, ha 2 Morgan-s dolgozók is a vezetők?

Itt jön a rekurziót. indul a tetején a hierarchia. A nyári költség 0 $. elkezdi Jack, majd ellenőrizze, ha bármilyen vezetők a munkavállalók. ha talál olyan közülük, ellenőrizze, ha van olyan vezetők, mint az alkalmazottak, és így tovább. Hozzá 300 $ a nyári költsége minden alkalommal, amikor talál egy menedzser. Ha elkészült, Jack, menj John, alkalmazottai, majd Morgan.

Soha nem tudni, hogy mennyi ciklust fogsz menni, mielőtt elindul a választ, úgy, hogy tudja, hány vezetők van, és hány olcsó tud tölteni.

A rekurzió egy fa, ágak és levelek, az úgynevezett szülők és gyermekek volt. Ha olyan rekurzív algoritmust, akkor többé-kevésbé tudatosan építenek egy fa az adatokat.

Válaszolt 04/05/2010 13:50
a forrás felhasználó

szavazat
1

Magyarán rekurzió jelenti, hogy ismételje someting újra és újra.

A programozás során az egyik példája az a függvény hívása belül is.

Nézd meg a következő példát számítási faktoriálisát száma:

public int fact(int n)
{
    if (n==0) return 1;
    else return n*fact(n-1)
}
Válaszolt 04/05/2010 13:48
a forrás felhasználó

szavazat
1

A rekurzió az a folyamat, amikor a módszer hívást iself, hogy képes legyen végre egy bizonyos feladat. Csökkenti redundency kódot. A legtöbb recurssive funkciók vagy módszerek kell egy condifiton megtörni a recussive hívják, azaz meg kell akadályozni nevezte magát, ha a feltétel teljesül - ez megakadályozza, hogy a teremtő egy végtelen ciklus. Nem minden funkció alkalmas arra, hogy kell használni, ismételhető.

Válaszolt 04/05/2010 13:42
a forrás felhasználó

szavazat
1

annak a módját, hogy a dolgokat újra és újra a végtelenségig, hogy minden lehetőséget használják.

például, ha akar, hogy minden a linkek egy html oldalon eldönthetjük, hogy rekurzív, mert amikor megkapja az összes hivatkozást az 1. oldalon, akkor szeretnénk, hogy az összes hivatkozást az egyes linkeket az első oldalon. Ezután minden egyes linket egy newpage akkor érdemes ezeket a kapcsolatokat és így tovább ... más szóval ez egy függvény, amely magát belülről is.

ha ezt szüksége van egy módja annak, hogy tudja, mikor kell abbahagyni, különben lesz egy végtelen ciklust ad hozzá egy egész param a funkció nyomon követni a ciklusok számát.

C # lesz, valahogy így:

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;
}
Válaszolt 04/05/2010 13:02
a forrás felhasználó

szavazat
1

„Ha van egy kalapács, mindent néz ki, mint egy köröm.”

A rekurzió egy problémamegoldó stratégia hatalmas problémát, ahol minden lépésben csak „viszont 2 kis dolgokat egy nagyobb dolog”, minden alkalommal ugyanazt a kalapácsot.

Példa

Tegyük fel, hogy az asztalon van borítva szervezetlen rendetlenség 1024 papírokat. Hogyan csinál egy szép, tiszta halom papír a rendetlenség, a rekurzió?

  1. Divide: Spread a lapokat, így akkor már csak egy lapot minden egyes „stack”.
  2. conquer:
    1. Menj körbe, amivel minden egyes lap tetején egy másik lapot. Most már van halom 2.
    2. Menj körbe, amivel minden 2-stack tetején egy 2-verem. Most már rengeteg 4.
    3. Menj körbe, amivel minden 4-stack tetején egy 4-verem. Most már van halom 8.
    4. ... egyre tovább ...
    5. Most már van egy hatalmas halom 1024 lap!

Figyeljük meg, hogy ez elég intuitív, eltekintve számítva mindent (ami nem feltétlenül szükséges). Lehet, hogy nem megy egészen az 1 lapos halom, a valóságban, de lehet, és ez még mindig működik. A fontos része a kalapács: a karja, akkor mindig tedd egy halom tetejére a másik, hogy egy nagyobb stack, és ez nem számít (az ésszerűség határain belül), hogy milyen nagy vagy verem.

Válaszolt 04/05/2010 12:54
a forrás felhasználó

szavazat
1

Rekurzió, mivel azokra a programozás alapvetően egy funkció belülről a saját meghatározását (belső is), különböző paraméterekkel, hogy egy feladat elvégzését.

Válaszolt 04/05/2010 12:25
a forrás felhasználó

szavazat
1

Meg akarja használni, amikor csak van egy fa struktúra. Ez nagyon hasznos az olvasás XML.

Válaszolt 21/08/2008 14:18
a forrás felhasználó

szavazat
1

Mario, nem értem miért használnak rekurzív hogy például .. miért nem egyszerűen végigjárjuk minden bejegyzés? Valami ilyesmi:

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;
}

A fenti módszer gyorsabb, és egyszerűbb. Nincs szükség kezelhető rekurzió helyett egy egyszerű hurok. Azt hiszem, ezek a különféle példákat ezért rekurzív kap egy rossz rap. Még a kanonikus faktoriális függvény például jobban végre egy hurkot.

Válaszolt 06/08/2008 04:19
a forrás felhasználó

szavazat
0

Valójában a jobb rekurzív megoldás faktoriális kell:

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);
}

Mivel ez a verzió Tail rekurzív

Válaszolt 21/08/2008 14:39
a forrás felhasználó

szavazat
0

Használom rekurziót. Mi köze van köze, amelynek CS mértékben ... (amit nem mellesleg)

Gyakori felhasználási találtam:

  1. sitemaps - recurse keresztül fájlrendszer kezdődnek dokumentum gyökér
  2. pókok - mászik át a honlapján, hogy megtalálja az e-mail cím, hivatkozások, stb
  3. ?
Válaszolt 06/08/2008 04:13
a forrás felhasználó

szavazat
0

Létrehoztam egy rekurzív függvényt összefűzésére listáját húrok egy elválasztó közöttük. ÉN használ ez többnyire létrehozása SQL kifejezések engedünk mezők listája a „ példány ” és a „ vessző + space ”, mint az elválasztó. Itt a funkció (használ némi Borland Builder natív adattípusok, de lehet igazítani, hogy illeszkedjen bármely más környezet):

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;
}

Úgy hívom ezt az utat:

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

Képzeld el, hogy egy tömb neve „ mező ” ezekkel az adatokkal benne: „ ALBUMNAME ”, „ releasedate ”, „ labelId ”. Akkor hívja a funkciót:

ArrangeString(fields, 0, ", ");

Mivel a függvény elkezd dolgozni, akkor a változó „ eredmény ” kapja az értéket a 0 helyzetbe a tömb, amely „ ALBUMNAME ”.

Ezután ellenőrzi, hogy a helyzet ez foglalkozik az utolsó. Mivel ez nem, akkor összefűzi az eredményt az elválasztó és az eredmény függvényében, amely, ó Istenem, ez ugyanaz a funkciója. De ezúttal, nézd meg, hogy hívja magát, hogy 1 a helyzetbe.

ArrangeString(fields, 1, ", ");

Ez ismétlődik, ami a LIFO bolyhos, amíg el nem éri azt a pontot, ahol a pozíció foglalkoznak az utolsó, így a függvény visszatérési csak az elem azon a helyen a listán, nem egybetoldjuk többé. Ezután a halom összefűzött hátra.

Megvan? Ha nem, van egy másik módja annak, hogy magyarázza meg. : O)

Válaszolt 06/08/2008 04:00
a forrás felhasználó

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