Rekursion är definitionen, beskrivningen, bilden av ett objekt eller en process inom detta objekt eller själva processen, det vill säga situationen när objektet är en del av sig självt. Termen "rekursion" används inom olika speciella kunskapsområden - från lingvistik till logik , men finner den bredaste tillämpningen inom matematik och datavetenskap .
I matematik hänvisar rekursion till metoden att definiera funktioner och talserier: en rekursivt given funktion bestämmer sitt värde genom att referera till sig själv med andra argument. I det här fallet är två alternativ möjliga:
Ett annat exempel på rekursion i matematik är en talsekvens , given av en rekursiv formel , där varje på varandra följande term i sekvensen beräknas som ett resultat av en funktion av de n föregående termerna. Således, med hjälp av ett ändligt uttryck (som är en kombination av en rekursiv formel och en uppsättning värden för de första n termerna i en serie), kan en oändlig sekvens definieras.
Nära besläktad med rekursion är matematisk induktion : det är ett naturligt sätt att bevisa egenskaperna hos funktioner på naturliga tal , givet rekursivt i termer av deras mindre värden.
Inom matematiken betraktas en klass av så kallade "primitivt rekursiva" funktioner separat. Definitionen av en primitiv rekursiv funktion är också rekursiv, den definierar en uppsättning primitiva funktioner och en uppsättning regler; en funktion är primitiv rekursiv om den kan representeras som en kombination av primitiva rekursiva funktioner bildade enligt dessa regler.
Exempel på rekursion i matematik:
I programmering är rekursion ett anrop till en funktion ( procedur ) från sig själv, direkt ( enkel rekursion ) eller genom andra funktioner ( komplex eller indirekt rekursion ), till exempel en funktion anropar en funktion och en funktion anropar en funktion . Antalet kapslade funktions- eller proceduranrop kallas rekursionsdjupet. Ett rekursivt program låter dig beskriva en upprepande eller till och med potentiellt oändlig beräkning, och utan explicit upprepning av delar av programmet och användning av loopar.
En strukturellt rekursiv funktion på toppnivån är alltid en greninstruktion (val av ett av två eller flera alternativ beroende på villkoren, vilket i detta fall är lämpligt att kalla "rekursionsavslutningsvillkoret"), som har två eller flera alternativa grenar, av vilka även om minst en är rekursiv och minst en är terminal . Den rekursiva grenen exekveras när rekursionsavslutningsvillkoret är falskt och innehåller åtminstone ett rekursivt anrop - ett direkt eller indirekt anrop av funktionen till sig själv. Terminalgrenen exekveras när rekursionsavslutningsvillkoret är sant; den returnerar något värde utan att göra ett rekursivt anrop. En välskriven rekursiv funktion måste säkerställa att efter ett ändligt antal rekursiva anrop uppnås rekursionsavslutningsvillkoret, vilket får kedjan av successiva rekursiva anrop att bryta och återvända.
Förutom funktioner som gör ett rekursivt anrop på varje rekursiv gren, finns det fall av "parallell rekursion" där två eller flera rekursiva anrop görs på samma rekursiva gren. Parallell rekursion är typiskt vid bearbetning av komplexa datastrukturer såsom träd. Det enklaste exemplet på en parallell-rekursiv funktion är beräkningen av Fibonacci-serien, där för att få värdet på den n:te termen är det nödvändigt att beräkna (n-1)-th och (n-2)-th .
Implementeringen av rekursiva funktionsanrop i praktiskt använda språk och programmeringsmiljöer förlitar sig som regel på anropsstackmekanismen - funktionens returadress och lokala variabler skrivs till stacken , på grund av vilket varje nästa rekursiva anrop till den här funktionen använder sin egen uppsättning lokala variabler och på grund av detta fungerar den korrekt. Baksidan av denna ganska enkla mekanism är att varje rekursivt anrop kräver en viss mängd dator- RAM , och om rekursionen är för djup kan anropsstacken svämma över .
Frågan om önskvärdheten av att använda rekursiva funktioner i programmering är tvetydig: å ena sidan kan den rekursiva formen vara strukturellt enklare och tydligare, särskilt när den implementerade algoritmen i sig är väsentligen rekursiv. Dessutom har vissa deklarativa eller rent funktionella språk (som Prolog eller Haskell ) helt enkelt inte syntaktiska medel för att organisera loopar, och rekursion i dem är den enda tillgängliga mekanismen för att organisera upprepade beräkningar. Å andra sidan rekommenderas det generellt att undvika rekursiva program som leder (eller under vissa omständigheter kan leda) till för stort rekursionsdjup. Exemplet med rekursiv beräkning av faktorial, som är utbrett i utbildningslitteraturen, är alltså snarare ett exempel på hur man inte använder rekursion, eftersom det leder till ett tillräckligt stort rekursionsdjup och har en uppenbar implementering i form av en konventionell cyklisk algoritm.
Det finns en speciell typ av rekursion som kallas " svansrekursion " (strukturen av en rekursiv algoritm är sådan att det rekursiva anropet är den sista operationen som utförs i funktionen, och dess resultat returneras direkt som resultatet av funktionen). Tolkar och kompilatorer av funktionella programmeringsspråk som stöder kodoptimering (källa eller körbar) konverterar automatiskt svansrekursion till iteration , vilket säkerställer exekvering av svansrekursionsalgoritmer i en begränsad mängd minne. Sådana rekursiva beräkningar, även om de formellt är oändliga (till exempel när man använder rekursion för att organisera arbetet i ett skal som accepterar användarkommandon), leder aldrig till minnesutmattning . Men programmeringsspråksstandarder definierar inte alltid tydligt exakt vilka villkor en rekursiv funktion måste uppfylla för att översättaren ska garanteras omvandla den till en iteration. Ett av de sällsynta undantagen är Scheme-språket ( en dialekt av Lisp-språket ), vars beskrivning innehåller all nödvändig information.
Teoretiskt kan alla rekursiva funktioner ersättas av en loop och en stack . En sådan modifiering är dock som regel meningslös, eftersom den bara leder till att den automatiska lagringen av sammanhanget i anropsstacken ersätts med manuell exekvering av samma operationer med samma eller mer minnesförbrukning. Ett undantag kan vara situationen när den rekursiva algoritmen måste modelleras på ett språk där rekursion är förbjuden.
Till skillnad från explicit cykliska program, finns det inget behov av att artificiellt introducera en invariant för att bevisa riktigheten av rekursiva . Det analytiska beviset för riktigheten av en rekursiv funktion reduceras till metoden för matematisk induktion, det vill säga till beviset för följande påståenden:
Det följer av summan av de första och andra påståendena att om terminalgrenen nås (och detta betyder i alla fall när beräkningen av funktionen visar sig vara slutgiltig), kommer funktionen att returnera det korrekta resultatet. Den tredje propositionen bevisar att varje beräkning kommer att vara finit. Därför kommer alla funktionsanrop med rätt parametrar att returnera det korrekta resultatet (med den uppenbara "tekniska" varningen - om rekursionsdjupet inte är så stort att det orsakar ett minnesspill).
Rekursiv datadefinition uppstår när en datastruktur (post, objekt) innehåller ett kapslat objekt som är strukturellt likt sig självt eller (oftast) en referens till samma objekt. Fördelen med att rekursivt definiera ett objekt är att en sådan finit definition kan beskriva en potentiellt oändlig datastruktur. Liknande strukturer används vid beskrivning av listor och grafer . Listbeskrivningsexempel ( C ):
struct element_of_list { struct element_of_list * nästa ; /* pekare till nästa element av samma typ */ intdata ; _ /* lite data */ };Eftersom ett oändligt antal kapslade objekt inte kan passa in i ändligt minne, är sådana rekursivt definierade strukturer i verkligheten alltid ändliga. I de sista (terminala) cellerna skrivs vanligtvis tomma pekare, som också är flaggor som indikerar för programmet som bearbetar strukturen att dess slut har nåtts.
Den rekursiva datastrukturen orsakar ofta användningen av rekursion för att bearbeta dessa data. Under de senaste åren har konceptet med så kallad " lat utvärdering " blivit populärt, enligt vilken data som bearbetas av programmet beräknas endast när det behövs. Implementeringen av detta koncept har lett till uppkomsten på vissa språk ( Haskell , Python ) av förmågan att beskriva potentiellt oändliga, inklusive rekursiva sekvenser utan explicita begränsningar för generering av objekt och fritt arbeta med dem.
Ett klassiskt exempel på oändlig rekursion är två speglar placerade mitt emot varandra : de bildar två korridorer av minskande spegelreflektioner.
Ett annat exempel på oändlig rekursion är självexciteringseffekten (positiv återkoppling) hos elektroniska förstärkningskretsar, när signalen från utgången går till ingången, förstärks, går tillbaka till kretsens ingång och förstärks igen. Förstärkare för vilka detta driftsätt är standard kallas självoscillatorer .
Inom lingvistik är rekursion ett språks förmåga att generera kapslade meningar och konstruktioner. Grundsatsen " katten åt musen " kan utökas med rekursion som " Vanya gissade att katten åt musen" , ytterligare som " Katya vet att Vanya gissade att katten åt musen", och så vidare. Rekursion anses vara en av de språkliga universalerna , det vill säga det är karakteristiskt för alla naturliga språk. Emellertid har den möjliga frånvaron av rekursion i ett av språken i Amazonas - Pirahana , vilket noteras av lingvisten Daniel Everett [1] , nyligen aktivt diskuterats .
rekursion se rekursion
Jag hittade följande korta information:
"SEPULS är ett viktigt inslag i Ardrites civilisation (se) från planeten Enteropia (se). Se SEPULCARIA.
Jag följde detta råd och läste:
"SEPULCARIA - enheter för sepulation (q.v.)".
Jag sökte efter "Sepulenia"; det löd:
”SEPULATION - ockupationen av Ardrits (se) från planeten Enteropia (se). Se SEPULS.
fraktaler | ||
---|---|---|
Egenskaper | ||
De enklaste fraktalerna | ||
konstig attraktion | Multifraktal | |
L-system | Utrymmesfyllande kurva | |
Bifurkationsfraktaler | ||
Slumpmässiga fraktaler | ||
människor | ||
Relaterade ämnen |