Sade İngilizce'de özyineleme nedir?


74

Özyineleme fikri gerçek dünyada pek yaygın değildir. Yani, acemi programcıları için biraz kafa karıştırıcı görünüyor. Her ne kadar sanırım, yavaş yavaş bu konsepte alıştılar. Öyleyse, fikri kolayca kavramaları için ne güzel bir açıklama olabilir?




1
Özyineleme, bir fonksiyonun kendisini çağırabildiği zamandır. “Ad alanlarını ve kapsamını ve parametrelerin bir fonksiyona nasıl geçtiğini tamamen anlarsanız, o zaman zaten özyinelemeyi biliyorsunuz. Örnekler gösterebilirim, ancak kendi başlarına nasıl çalıştıklarını çözebilmelisiniz.” Öğrenciler genellikle, özyinelemeyle çok fazla uğraşmazlar çünkü kafa karıştırıcıdır, fakat değişken kapsam / ad alanını sıkı bir şekilde kavrayamazlar. Özyinelemeye dalmadan önce, öğrencilerin farklı kapsamlarda bilerek değişkenlere verdiğiniz bir program boyunca izlerini sürdürebildiğinden emin olun, aynı adı karıştırın.
dspyz


1
Özyinelemeyi Anlamak İçin, Önce Özyinelemeyi
Anlamanız Gerekiyor

Yanıtlar:


110

Açıklamak için Özyinelemeyi , genellikle her iki denemek için farklı bir açıklama bir arada kullanın:

  • kavramı açıklar
  • neden önemli olduğunu açıklamak
  • Nasıl elde edileceğini açıkla.

Yeni başlayanlar için Wolfram | Alpha , Wikipedia'dan daha basit bir şekilde tanımlar :

Her bir terimin belirli bir matematiksel işlemi tekrarlayarak üretileceği bir ifade.


Matematik

Eğer öğrenciniz (veya siz de açıklayacağınız kişi, bundan sonra öğrenciyi söyleyeceğim), en azından bazı matematiksel geçmişe sahipse, seriyi inceleyerek ve yinelemeyle ilgili düşüncelerini ve yinelenme ilişkilerini inceleyerek açıkça yinelemeyle karşılaşmışlardır .

Başlamak için çok iyi bir yol, bir dizi ile göstermek ve özyinelemenin ne demek olduğunu söylemek.

  • matematiksel bir işlev ...
  • ... bu, n'inci bir öğeye karşılık gelen bir değeri hesaplamaya çağırıyor ...
  • ... ve bazı sınırları tanımlar.

Genellikle, ya en iyi ihtimalle bir "ha ha, ne" "elde edersin, çünkü hala kullanmıyorlar, ya da muhtemelen çok derin bir horlama.


Kodlama Örnekleri

Geri kalanı için, aslında ben sunulan şeyin detaylı versiyonu Zeyilname ait cevabım için size ilgili işaretçiler işaret soruya (kötü kelime oyunu).

Bu aşamada öğrencilerim genellikle ekrana bir şeylerin nasıl yazdırılacağını bilirler. C kullandığımızı varsayarsak, writeveya kullanarak tek bir karakterin nasıl yazdırılacağını bilirler printf. Ayrıca kontrol döngülerinden de haberdarlar.

Genelde birkaç tekrarlayan ve basit programlama problemini çözene kadar başvuruyorum:

  • faktöryel operasyon,
  • bir alfabe yazıcısı,
  • tersine çevrilmiş bir alfabe yazıcısı,
  • exponentation çalışma.

Çarpınım

Faktoring, anlaşılması gereken çok basit bir matematik kavramdır ve uygulama matematiksel temsiline çok yakındır. Ancak, ilk başta alamayabilirler.

Faktoring Operasyonunun Özyinelemeli Tanımı

alfabe

Alfabe versiyonu, özyinelemeli ifadelerinin sırası hakkında düşünmeyi öğretmek için ilginçtir. İşaretçilerde olduğu gibi, sadece size rastgele çizgiler atarlar. Nokta bir döngü koşulları değiştirerek ya tarafından tersine çevrilebilir gerçekleşme getirmek için VEYA sadece işlevinde tabloların sırasını ters çevirerek. Alfabeyi basmanın yardımı budur, çünkü onlar için görsel bir şeydir. Basitçe, her arama için bir karakter yazdıracak ve bir sonraki (veya önceki) bir karakteri yazmak için kendisini tekrar tekrar çağıracak bir fonksiyon yazmasını sağlayın.

FP fanları, çıktı akışına baskı malzemelerinin şu an için bir yan etki olduğu gerçeğini atlayın ... FP-cephesinde fazla can sıkıcı olalım. (Eğer liste destekli bir dil kullanıyorsanız, her yinelemede bir listeyi birleştirmek için çekinmeyin ve sadece son sonucu yazdırın. .

Üs

Üsümleme sorunu biraz daha zordur ( bu öğrenme aşamasında ). Açıkçası, konsept faktoring için olduğu gibi tamamen aynıdır ve birden fazla parametreye sahip olmanız dışında herhangi bir karmaşıklık yoktur. Ve bu genellikle insanları şaşırtmak ve başlangıçta onları atmak için yeterlidir.

Basit şekli:

Üslem İşleminin Basit Formu

yinelenme ile böyle ifade edilebilir:

Üs Kullanım İşlemi İçin Nüks İlişkisi

Daha güçlü

Bu basit problemler gösterildikten ve öğreticilerde yeniden uygulandıktan sonra, biraz daha zor (ama çok klasik) alıştırmalar verebilirsiniz:

Not: Yine, bunlardan bazıları gerçekten zor değil ... Soruna tam olarak aynı açıdan veya biraz farklı bir açıdan yaklaşıyorlar. Ancak pratik mükemmelleştirir.


Yardımcılar

Referans

Bazı okumalar asla acıtmaz. Peki, ilk başta olacak ve daha da kaybolmuş hissedecekler. Bu, üzerinde büyüyen ve bir gün nihayet elde edeceğinin farkına varıncaya kadar kafanın arkasında oturan bir şey. Ve sonra okuduğun bu şeyleri tekrar düşünürsün. Tekrarlama , Bilgisayar Bilimleri alanında yineleme ve nüks ilişki Vikipedi sayfaların şimdilik yapardı.

Seviye / Derinlik

Öğrencilerinizin çok fazla kodlama tecrübesi olmadığını varsayalım, kod saplamaları sağlayın. İlk denemeden sonra, tekrarlama seviyesini gösterebilecek bir yazdırma işlevi verin. Seviyenin sayısal değerini yazdırmak yardımcı olur.

Çekmeceli Yığın Diyagramı

Basılı bir sonucun (veya seviyenin çıktısının) girilmesi, programınızın ne yaptığını, çekmeceler gibi yığın bağlamlarını veya dosya sistemi gezgini içindeki klasörleri açma ve kapama işleminin başka bir görsel sunumunu sağladığından da yardımcı olur.

Özyinelemeli Kısaltmalar

Öğrenciniz zaten biraz bilgisayar kültürüne alıştıysa, özyinelemeli kısaltmalar kullanan isimlerle bazı projeler / yazılımlar kullanabilirler . Özellikle GNU projelerinde bir süredir devam eden bir gelenek oldu. Bazı örnekler:

yinelemeli:

  • GNU - "GNU'nun Unix'i Değil"
  • Nagios - "Nagios Azizlikte Israr Etmeyecek"
  • PHP - "PHP Köprü Metin Ön İşlemcisi" (ve köken "Kişisel Giriş Sayfası")
  • Şarap - "Şarap Emülatör Değil"
  • Zile - "Zile Kayıp Emacs"

Karşılıklı özyinelemeli:

  • HURD - "Unix-ikame Daemonların HIRD'i" (burada HIRD "Derinlik Temsil eden Arayüzlerin HURD'si")

Onların kendileriyle gelmeye çalışmasını sağlayın.

Benzer şekilde, Google'ın özyinelemeli arama düzeltmesi gibi özyinelemeli mizah örnekleri de vardır . Özyineleme hakkında daha fazla bilgi için bu cevabı okuyun .


Tuzaklar ve İleri Öğrenme

İnsanların genellikle uğraştığı ve cevaplarını bilmen gereken bazı konular.

Neden, aman Tanrım Neden ???

Neden bunu yapasın? İyi ama açık olmayan bir neden, bir sorunu bu şekilde ifade etmenin genellikle daha kolay olmasıdır. Çok iyi olmayan ama bariz bir sebep, genellikle daha az yazmaya ihtiyaç duymasıdır (sadece özyinelemeyi kullandıkları için soooo l33t hissetmelerini sağlayın ...).

Özyinelemeli bir yaklaşım kullanırken bazı sorunları çözmek kesinlikle daha kolaydır. Genellikle, Divide and Conquer paradigmasını kullanarak çözebileceğiniz her türlü problem, çok dallı bir özyineleme algoritmasına uyacaktır.

Yine N nedir?

Neden nya da (değişkeninin adı ne olursa olsun) her zaman neden farklı? Yeni başlayanlar genellikle bir değişkenin ve parametrenin ne olduğunu nve programınızdakilerin nasıl farklı değerlere sahip olabileceğini anlamada sorun yaşarlar . Şimdi, eğer bu değer kontrol döngüsü veya özyineleme ise, bu daha da kötüdür! İyi olun ve her yerde aynı değişken adlarını kullanmayın ve parametrelerin sadece değişken olduğunu açıkça belirtin .

Bitiş Koşulları

Bitiş koşulumu nasıl belirlerim? Bu kolay, sadece yüksek sesle çıkanları söylemelerini isteyin. Mesela faktörlük için 5, sonra 4, sonra ... 0 ile başlayınız.

Şeytan Ayrıntıda

Kuyruk çağrısı optimizasyonu gibi şeyler hakkında henüz erken konuşmayın . Biliyorum, biliyorum, TCO iyi, ama ilk başta umursamıyorlar. Kafalarını işlemin etrafına, kendileri için uygun olacak şekilde sarmaları için zaman verin. Daha sonra tekrar dünyalarını paramparça etmekte özgürsünüz, ama bir mola verin.

Benzer şekilde, arama yığını ve hafıza tüketimi hakkında ilk dersten bahsetme ve ... yığın ... taşma . Sık sık bu aşamada doğru bir şekilde bir döngü yazabildiklerinde, özyinme hakkında bilmesi gereken her şey hakkında 50 slaydın olduğu dersleri gösteren öğrencilere özel olarak ders veriyorum. Bu, bir referansın daha sonra nasıl yardım edeceğine dair güzel bir örnek ama şu anda sadece sizi derinden karıştırıyor .

Ancak lütfen, zamanında, yinelemeli veya özyinelemeli rotayı izlemenin nedenleri olduğunu açıkça belirtin .

Karşılıklı özyineleme

İşlevlerin özyinelemeli olabileceğini ve hatta birçok çağrı noktasına (8-kraliçe, Hanoi, Fibonacci, hatta bir mayın tarama gemisi için bir keşif algoritmasına) sahip olduklarını gördük. Peki ya karşılıklı özyinelemeli aramalar ? Burada matematikle de başlayın. f(x) = g(x) + h(x)nerede g(x) = f(x) + l(x)ve hve lsadece şeyler yapın.

Sadece matematiksel serilerden başlamak, sözleşmeyi ifadeler tarafından açıkça tanımlandığı için yazmayı ve uygulamayı kolaylaştırır. Örneğin, Hofstadter Kadın ve Erkek Dizileri :

Hofstadter'in Erkek ve Kadın Dizileri

Ancak kod açısından, bu karşılıklı özyinelemeli çözümün uygulanmasının genellikle tekrarını kod yol açar ve yerine tek özyinelemeli forma aerodinamik gerektiğini belirtmek gerekir (Bkz Peter Norvig 'ın her Sudoku Bulmaca Çözme .


5
Cevabınızı neredeyse 5 veya 6 saat sonra gördükten sonra okuyorum. Güzeldi ama burada diğer kullanıcıları çekmek için çok uzun sanırım. Burada özyinelemeyi öğretme hakkında birçok şey öğrendim. Bir öğretmen olarak, özyinelemeyi öğretme fikrimi değerlendirir misiniz lütfen- programmers.stackexchange.com/questions/25052/…
Gulshan

9
@ Gülhan, bu cevabın olacağı kadar kapsamlı olduğunu düşünüyorum ve sıradan bir okuyucu tarafından kolayca gözden geçirildi. Bu yüzden static unsigned int vote = 1;, benden bir alır . Statik mizahı affet, eğer istersen :) Bu, şu ana kadarki en iyi cevap.
Tim Post

1
@Gulsan: Sadece öğrenmek isteyenler, vakit ayırmaya isteklidir, doğru dürüst olur :) Gerçekten umursamıyorum. Bazen, kısa bir cevap zarif olabilir ve genel bir kavramı başlatmak veya açıklamak için birçok yararlı ve gerekli bilgiyi iletir. Sadece bunun için daha uzun bir cevap istedim ve OP, "doğru" cevabını aldığım bir sorudan bahsetti ve benzer bir cevap sorduğunda, aynı cevabı vermeyi uygun buldum. Bir şey öğrenmene sevindim.
haylem

@ Gülhan: Şimdi cevabınızla ilgili: ilk nokta beni çok karıştırdı, söylemeliyim. Özyinelemeli işlevler kavramını zaman içinde durumu aşamalı olarak değiştiren bir şey olarak tanımlamanızı seviyorum, ancak sunum şeklinizin biraz garip olduğunu düşünüyorum. 3 puanınızı okuduktan sonra birçok öğrencinin Hanoi'yi aniden çözmesini beklemiyorum. Ancak bu sadece bir ifade sorunu olabilir.
haylem

Aynı değişkenin farklı özyineleme derinliklerinde farklı değerlere sahip olabileceğini göstermenin iyi bir yolunu gördüm: öğrencilerin özyinelemeli kodları izleyerek attıkları adımları ve değişkenlerin değerlerini yazmalarını düşünün. Özyinelemeye ulaştığında, tekrar yeni bir parçaya başlamalarını sağlayın. Bir çıkış durumuna ulaştıklarında önceki parçaya dönmelerini sağlayın. Bu aslında bir çağrı yığınını taklit ediyor, ancak bu farklılıkları göstermek için iyi bir yol.
Andy Hunt,

58

Aynı işlevin içindeki bir işlevin çağrılması.


2
Bu gerçekten başlamak için en iyi açıklama. Basit ve konuya; Bu özeti oluşturduktan sonra, tüm kafa gezisi ayrıntılarına gidin.
16'da jhocking

27

Özyineleme kendini çağıran bir işlevdir.

Nasıl kullanılacağı, ne zaman kullanılacağı ve kötü tasarımdan kaçınmanın bilinmesi önemlidir, bu da kendiniz için denemenizi ve ne olduğunu anlamanızı gerektirir.

Bilmeniz gereken en önemli şey, hiç bitmeyen bir döngü elde etmemek için çok dikkatli olmaktır. Pramodc84'ten sorunuza verilen cevap şu hatadır: Asla bitmez ...
Özyinelemeli bir işlev kendini tekrar arayacak mı yoksa tekrar mı arayacağına karar vermek için her zaman bir durumu kontrol etmelidir.

Özyinelemeyi kullanmak için en klasik örnek, derinliği statik sınırları olmayan bir ağaçla çalışmaktır. Bu özyinelemeyi kullanmanız gereken bir görevdir.


Tekrarlayan bir şekilde daha iyi olsa da, son paragrafınızı yinelemeli bir şekilde uygulayabilirsiniz. “Nasıl kullanılır, ne zaman kullanılır ve kötü tasarımdan nasıl kaçınılır, bilmek önemlidir, bu da kendiniz için denemenizi ve ne olduğunu anlamanızı gerektirir.” Sorunun amacının bir açıklama yapmak olduğunu düşündüm. bu tür şeyler.
haylem

@haylem: “Nasıl kullanılır, ne zaman kullanılır ve kötü tasarımdan nasıl kaçınırsınız?” cevabını doğru buluyorsunuz, OP'nin ne istediğine (sadece değil) kendinize deneyin “dediğim gibi), ancak buradaki bir soruya hızlı bir cevap vermek yerine, daha öğretici türden kapsamlı bir ders gerektirecektir. Yine de cevabınız ile çok iyi bir iş yaptınız . Bunun için +1 ... Kavramı daha iyi kavraması gerekenler cevabınızı okumaktan fayda sağlayacaklar.
korku

birbirini çağıran bir çift fonksiyon ne olacak? Bazı koşullara ulaşılıncaya kadar A'yı tekrar çağıran B aramaları. Bu hala özyineleme olarak kabul edilir mi?
santiagozky

Evet, fonksiyon ahala dolaylı olarak (çağırarak b) kendisini çağırır .
tür

1
@ santiagozky: Türünün dediği gibi, hala özyinelemede. Ancak yapmamasını tavsiye ederim. Özyineleme kullanılırken özyinelemenin uygulandığı kodda açıkça anlaşılmalıdır. Kendisini dolaylı olarak başka bir işlevden çağırıyorsanız, neler olduğunu görmeyi çok zorlaştırır. Bir işlevin kendisini etkili bir şekilde çağırdığını bilmiyorsanız, (ya da bu işlevi oluşturmayan bir başkasının) özyinelemeye (koddaki işlevselliği değiştirirken) bir koşul getirme durumuna girebilir ve sona erersiniz. hiç bitmeyen bir döngü ile ölü kilitli.
Awe

21

Özyinelemeli programlama, kendi sürümlerini çözmeyi kolaylaştıracak bir sorunu aşamalı olarak azaltma sürecidir.

Her özyinelemeli işlev eğilimindedir:

  1. işlemek için bir liste veya başka bir yapı ya da sorun
  2. geçerli nokta / adımla ilgilenmek
  3. kalanları / alt alan adlarını çağırır
  4. alt etki alanı çalışmasının sonuçlarını birleştirmek veya kullanmak

2. adım 3'ten önce olduğunda ve 4. adım önemsiz olduğunda (birleştirme, toplam veya hiçbir şey) bu kuyruk özyinelemesini sağlar . 2. Adım genellikle 3. adımdan sonra gelmelidir, çünkü mevcut adımı tamamlamak için problemin alt alanlarından gelen sonuçlara ihtiyaç duyulabilir.

Düz ileri bir ikili ağacın geçişini yapın. Geçiş, neyin gerekli olduğuna bağlı olarak ön sipariş, sipariş veya sipariş sonrasında yapılabilir.

   B
A     C

Ön sipariş: BAC

traverse(tree):
    visit the node
    traverse(left)
    traverse(right)

Sipariş: ABC

traverse(tree):
    traverse(left)
    visit the node
    traverse(right)

Sipariş sonrası: ACB

traverse(tree):
    traverse(left)
    traverse(right)
    visit the node

Çok sayıda özyinelemeli problem, bir harita işleminin özel durumlarıdır veya bir kat - sadece bu iki işlemin anlaşılması, özyineleme için iyi kullanım durumlarının önemli bir şekilde anlaşılmasını sağlayabilir.


Pratik özyinelemenin kilit bileşeni, daha büyük olanı çözmek için çözümü daha küçük bir soruna kullanma fikridir. Aksi takdirde, sadece sonsuz özyinelemeye sahipsiniz.
Barry Brown

@Barry Brown: Oldukça doğru. Bu
yüzden

Mutlaka söyleyemem ... Genellikle, bölücü ve fethetmek veya basit bir davaya dayanan bir tekrarlama ilişkisini gerçekten tanımladığınız durumlar için, genellikle durum böyledir. Ancak, probleminizin her
tekrarı için

1
@ Sean McMillan: Özyineleme, kendisine uygun olan alanlarda kullanıldığında güçlü bir araçtır. Çok sık sık , eldeki görevin gerçek doğasını büyük ölçüde engelleyen göreceli olarak önemsiz bazı meseleleri halletmenin akıllıca bir yolu olarak kullanıldığını görüyorum .
Orbling

20

OP, özyinelemenin gerçek dünyada olmadığını söyledi, ama ben farklı olmak için yalvarıyorum.

Gerçek dünyayı bir pizza kesme operasyonunu ele alalım. Pizzayı fırından çıkardın ve servis etmek için ikiye bölmek, sonra yarıya kesmek, sonra tekrar yarıya kesmek zorundasın.

İstediğiniz sonucu elde edene kadar tekrar tekrar yaptığınız pizzaları kesme işlemi (dilim sayısı). Argümanlar aşkına, kesilmemiş bir pizzanın bir dilim olduğunu söyleyelim.

İşte Ruby'de bir örnek:

def cut_pizza (existing_slices, İstenilen_slicler)
  existing_slices! = desired_slices
    # Herkesi beslemek için henüz yeterli dilimimiz yok,
    # Pizza dilimlerini kesiyoruz, böylece sayıları ikiye katlıyoruz
    new_slices = existing_slices * 2 
    # ve işte bu özyinelemeli çağrı
    cut_pizza (yeni üyeler, istenilen nesneler)
  Başka
    İstediğimiz dilim sayısına sahibiz,
    # burada tekrar etmeye devam etmek yerine
    exist_slices döndür
  son
son

pizza = 1 # bütün pizza, 'bir dilim'
cut_pizza (pizza, 8) # => 8 alacağız

Böylece gerçek dünya operasyonu bir pizza kesiyor ve özyineleme istediğiniz şeyi elde edene kadar tekrar tekrar aynı şeyi yapıyor.

Özyinelemeli işlevlerle uygulayabileceğiniz kırpmayı bulacaksınız:

  • Bileşik faizin birkaç ay boyunca hesaplanması.
  • Bir dosya sistemi üzerindeki bir dosyayı aramak (çünkü dosya sistemleri dizinlerden dolayı ağaçtır).
  • Genel olarak ağaçlarla çalışmayı içeren herhangi bir şey, sanırım.

Dosya adına göre bir dosyayı aramak için bir program yazmanızı ve bulunana kadar kendisini çağıran bir işlev yazmayı deniyorum, imza şöyle görünür:

find_file_by_name(file_name_we_are_looking_for, path_to_look_in)

Böylece buna şöyle diyebilirsin:

find_file_by_name('httpd.conf', '/etc') # damn it i can never find apache's conf

Bence basitçe, mekaniği programlama, kopyalamayı zekice kaldırmanın bir yolu. Bunu değişkenleri kullanarak yeniden yazabilirsiniz, ancak bu 'daha iyi' bir çözümdür. Bu konuda gizemli veya zor bir şey yok. Bir kaç özyinelemeli işlev yazacaksınız , programlama araç kutunuzdaki bir başka mekanik numaraya tıklayıp huzzahlayacaktır .

Ekstra Kredi Yukarıdaki cut_pizzaörnekte, 2 değerinde olmayan (yani 2 veya 4 veya 8 veya 16) bir dilim dilim istenirse, size çok yüksek bir hata düzeyi verir. Birisi 10 dilim için sorarsa hiç çalıştırmayacağı şekilde değiştirebilir misiniz?


16

Tamam, bu basit ve özlü tutmaya çalışacağım.

Özyinelemeli işlev kendilerini çağıran işlevlerdir. Özyinelemeli işlevi üç şeyden oluşur:

  1. Mantık
  2. Kendine bir çağrı
  3. Ne zaman sonlandırılmalı?

Özyinelemeli yöntemler yazmanın en iyi yolları, yinelemek istediğiniz işlemin sadece bir döngüsünü ele alarak basit bir örnek olarak yazmaya çalıştığınız yöntemi düşünmek, sonra çağrıyı yöntemin kendisine eklemek ve istediğiniz zaman eklemek sonlandırabilir. Öğrenmenin en iyi yolu, her şey gibi pratik yapmaktır.

Bu programcılar web sitesi olduğu için kod yazmaktan kaçınacağım ancak işte size iyi bir bağlantı

Bu şakayı yakalarsan, özyinelemenin ne demek olduğunu anlarsın.


Ayrıca bu cevaba bakınız: programmers.stackexchange.com/questions/25052/… (-:
Murph

4
Kesinlikle, özyineleme bir sonlandırma durumuna gerek duymaz; Özyinelemenin sona erdiğini garanti etmek özyinelemeli işlevin çözebileceği sorun türlerini sınırlandırır ve sonlandırmayı gerektirmeyen bazı anlamsal sunum türleri vardır.
Donal Fellows,

6

Özyineleme, bir programcının kendiliğinden bir işlev çağrısını çağırmak için kullanabileceği bir araçtır. Fibonacci dizisi, özyinelemenin nasıl kullanıldığı ders kitabı örneğidir.

Çoğu özyinelemeli kod hepsi yinelemeli işlev olarak ifade edilebilir, ancak genellikle dağınık. Diğer özyinelemeli programların iyi örnekleri, ağaçlar, ikili arama ağacı ve hatta quicksort gibi Veri Yapılarıdır.

Özyineleme, kodu daha az özensiz yapmak için kullanılır, genellikle daha yavaş olduğunu ve daha fazla bellek gerektirdiğini unutmayın.


Yavaş mı yoksa daha fazla hafıza mı gerektirdiği, eldeki kullanıma bağlıdır.
36'da

5
Fibonacci dizisi hesaplaması özyinelemeli yapmak için korkunç bir şeydir. Ağaç geçişi, özyinelemenin çok daha doğal bir kullanımıdır. Genelde, özyineleme iyi kullanıldığında, daha yavaş değildir ve daha fazla bellek gerektirmez, çünkü çağrı yığını yerine kendi yığınınızı tutmak zorunda kalırsınız.
David Thornley

1
@Dave: Buna itiraz etmiyorum, ama Fibonacci'nin başlamak için iyi bir örnek olduğunu düşünüyorum.
Bryan Harrington

5

Bunu kullanmayı seviyorum:

Mağazaya nasıl yürüyorsun?

Mağazanın girişindeyseniz, basitçe içinden geçin. Aksi takdirde, bir adım atın, ardından mağazanın sonuna kadar yürüyün.

Üç yönü eklemek çok önemlidir:

  • Önemsiz bir temel dava
  • Sorunun küçük bir parçasını çözme
  • Problemin kalanını tekrarlı olarak çözme

Aslında özyinelemeyi günlük yaşamda çok kullanıyoruz; biz sadece böyle düşünmüyoruz.


Özyineleme değildir. Eğer ikiye bölerseniz olur: Mağazanın yarısına kadar yürüyün, diğer yarısını yürüyün. Recurse.

2
Bu özyinelemedir. Bu bölünme ve fethetme değildir, ancak yalnızca bir özyineleme türüdür. Grafik algoritmaları (yol bulma gibi) özyinelemeli kavramlarla doludur.
deadalnix

2
Bu özyinelemektir, ancak zihinsel olarak "bir adım attıktan sonra depoya giden yolu yürüterek" yinelemeli bir algoritmaya dönüştürmek için çok kolay olduğundan, bunun kötü bir örnek olduğunu düşünüyorum. Bunun güzel yazılmış bir fordöngüyü anlamsız özyinelemeli bir işleve dönüştürmeye eşdeğer olduğunu düşünüyorum .
Brian,

3

Size göstereceğim en iyi örnek K & R ile C Programlama Dilidir: Bu kitapta (ve bellekten alıntı yapıyorum), özyineleme için indeks sayfasındaki giriş (yalnız) özyineleme hakkında konuştukları asıl sayfayı listeler ve Dizin sayfası da.


2

Josh K, Matroshka bebeklerinden zaten bahsetti . En kısa bebeğin bildiği bir şeyi öğrenmek istediğinizi varsayalım. Sorun şu ki, onunla gerçekten doğrudan konuşamıyorsunuz, çünkü ilk fotoğrafta soluna yerleştirilen uzun boylu bebeğin içinde yaşıyor . Bu yapı, (en uzun olanla sona erene kadar) (uzun boylu bebeğin içinde yaşar bir bebek) böyle gider.

Yani yapabileceğiniz tek şey, sorunuzu en uzun bebeğe sormak. En yüksek bebeğin (cevabı bilmeyen) sorunuzu kısa bebeğe (ilk resimde sağda olan) iletmesi gerekecektir. Ayrıca cevabı bulunmadığı için bir sonraki kısa bebeğe sorması gerekiyor. Mesaj en kısa bebeğe ulaşana kadar bu böyle devam edecek. En kısa bebek (gizli cevabı bilen tek kişi olan) cevabı bir sonraki uzun boylu bebeğe (solunda bulunur) cevap verir, bu da onu bir sonraki uzun boylu bebeğe iletir ... ve bu cevap cevaba kadar devam eder. en uzun bebek olan son hedefine ulaşır ve sonunda ... sen :)

Bu özyinelemenin gerçekten yaptığı şeydir. Bir işlev / yöntem beklenen cevabı alana kadar kendini çağırır. Bu nedenle özyinelemeli kod yazdığınızda özyinelemenin ne zaman sona ermesi gerektiğine karar vermek çok önemlidir.

En iyi açıklama değil ama umarım yardımcı olur.


2

Özyineleme n. - Bir işlemin kendisi olarak tanımlandığı bir algoritma tasarım deseni.

Klasik örnek bir sayının faktörünü bulmaktır, n! 0! = 1 ve diğer N doğal sayıları için, N faktörü, N sayısından küçük veya ona eşit olan tüm doğal sayıların çarpımıdır. = 6 * 5 * 4 * 3 * 2 * 1 = 720. Bu temel tanım, basit bir yinelemeli çözüm oluşturmanıza olanak sağlar:

int Fact(int degree)
{
    int result = 1;
    for(int i=degree; i>1; i--)
       result *= i;

    return result;
}

Ancak, işlemi tekrar inceleyin. 6! = 6 * 5 * 4 * 3 * 2 * 1. Aynı tanım, 5! = 5 * 4 * 3 * 2 * 1, yani 6 diyebiliriz! = 6 * (5!). Sırayla, 5! = 5 * (4!) Vb. Bunu yaparak, sorunu önceki tüm işlemlerimizin sonucunda gerçekleştirilen bir işleme indirgiyoruz. Bu, sonuçta tanımın bilindiği bir temel durum adı verilen bir noktaya indirgenir. Bizim durumumuzda, 0! = 1 (çoğu durumda da şunu söyleyebiliriz ki 1! = 1). Hesaplamada, genellikle algoritmaları çok benzer bir şekilde tanımlayabiliriz, yöntemin kendisini çağırması ve daha küçük bir girdi iletmesi, böylece problemi bir çok özyinelemede bir temel duruma indirger:

int Fact(int degree)
{
    if(degree==0) return 1; //the base case; 0! = 1 by definition
    else return degree * Fact(degree -1); //the recursive case; N! = N*(N-1)!
}

Bu, birçok dilde, üçlü operatör kullanılarak daha da basitleştirilebilir (bazen işleci bu şekilde sağlamayan dillerde Iif işlevi olarak görülür):

int Fact(int degree)
{
    //reads equivalently to the above, but is concise and often optimizable
    return degree==0 ? 1: degree * Fact(degree -1);
}

Avantajları:

  • Doğal ifade - birçok algoritma türü için bu, işlevi ifade etmenin çok doğal bir yoludur.
  • Azaltılmış LOC - Bir fonksiyonu özyinelemeli olarak tanımlamak genellikle çok daha özlüdür.
  • Hız - Bazı durumlarda, dil ve bilgisayar mimarisine bağlı olarak, bir algoritmanın tekrarlanması eşdeğer yinelemeli çözümden daha hızlıdır, çünkü genellikle bir işlev çağrısı yapmak donanım düzeyinde yinelemeli döngü için gereken işlemlerden ve bellek erişiminden daha hızlı bir işlemdir.
  • Bölünebilirlik - Birçok özyinelemeli algoritma “böl ve yönet” zihniyetindedir; işlemin sonucu, girişin iki yarısının her birinde gerçekleştirilen aynı işlemin bir sonucudur. Bu, çalışmayı her seviyede ikiye bölmenizi sağlar ve eğer varsa diğer yarısını işlenmesi için diğer bir "yürütme birimine" verebilirsiniz. Bu, yinelemeli bir algoritma ile genellikle daha zor veya imkansızdır.

Dezavantajları:

  • Anlamayı gerektirir - Neler olduğunu anlamak için özyineleme kavramını "kavramanız" ve bu nedenle etkili özyinelemeli algoritmalar yazmanız ve sürdürmeniz gerekir. Aksi takdirde sadece kara büyü gibi görünüyor.
  • Bağlama bağlı - Tekrarlamanın iyi bir fikir olup olmadığı, algoritmanın kendi açısından ne kadar zarif bir şekilde tanımlanabileceğine bağlıdır. Örneğin özyinelemeli bir SelectionSort oluşturmak mümkün olsa da, yinelemeli algoritma tipik olarak daha anlaşılırdır.
  • Çağrı yığını için RAM erişimini takas eder - Genellikle, işlev çağrıları, yinelemeyi yinelemeden daha hızlı hale getirebilen önbellek erişiminden daha ucuzdur. Ancak, genellikle yinelemeli bir algoritmanın çalışacağı hataların tekrarlanmasına neden olabilecek çağrı yığınının derinliği için bir sınır vardır.
  • Sonsuz özyineleme - Ne zaman duracağını bilmek zorundasın. Sonsuz yineleme de mümkündür, ancak dahil olan döngüsel yapıların anlaşılması ve böylece hata ayıklaması genellikle daha kolaydır.

1

Kullandığım örnek gerçek hayatta karşılaştığım bir problem. Bir konteyneriniz var (seyahate çıkmayı düşündüğünüz büyük bir sırt çantası gibi) ve toplam ağırlığı bilmek istiyorsunuz. Kabın içinde iki veya üç gevşek eşyaya ve bazı diğer kaplara (diyelim, çuvallara) sahipsin. Toplam kabın ağırlığı açık bir şekilde boş kabın ağırlığının yanı sıra içindeki her şeyin ağırlığıdır. Gevşek eşyalar için sadece tartılabilir ve çuvallar için sadece tartılabilir veya "her eşya çuvalının ağırlığı boş kabın ağırlığı ile içindeki her şeyin ağırlığıdır" diyebilirsiniz. Ve sonra, konteynırların içinde sadece gevşek nesnelerin olduğu bir noktaya gelinceye kadar konteynırlara konteynırların içine girmeye devam edersiniz. Bu özyineleme.

Bunun gerçek hayatta asla gerçekleşmeyeceğini düşünebilirsiniz, ancak belirli bir şirket veya bölümdeki kişilerin, yalnızca şirket için çalışan kişilerin, bölümlerin içindeki kişilerin bir karışımına sahip olduğunu saymaya veya eklemeye çalıştığını düşünebilirsiniz. oradaki bölümler bölümler vb. Veya bazı bölgelerde alt bölgeleri vb. Olan bölgeleri olan bir ülkedeki satışlar. Bu tür sorunlar her zaman işte olur.


0

Özyineleme birçok sayma problemini çözmek için kullanılabilir. Örneğin, bir partide (n> 1) bir grup insan bulunduğunu ve herkesin bir kez daha herkesin elini sıktığını varsayalım. Kaç tane el sıkışma gerçekleşti? Çözümün C (n, 2) = n (n-1) / 2 olduğunu biliyor olabilirsiniz, ancak özyinelemeli olarak şu şekilde çözebilirsiniz:

Diyelim ki sadece iki kişi var. Sonra (muayene ile) cevap açıktır 1.

Diyelim ki üç kişiniz var. Bir kişiyi dışarıda bırakın ve diğer iki kişiyle el sıkıştığını unutmayın. Bundan sonra, diğer iki kişi arasındaki el sıkışmalarını saymanız gerekir. Bunu zaten şimdi yaptık ve bu 1 oldu. Yani cevap 2 + 1 = 3.

Diyelim ki n insanınız var. Daha önce olduğu gibi aynı mantığı izleyerek, (n-1) + (n-1 kişi arasındaki el sıkışmalarının sayısı). Genişleyen, (n-1) + (n-2) + ... + 1 olur.

Özyinelemeli bir işlev olarak ifade edilir,

f (2) = 1
f (n) = n-1 + f (n-1), n> 2


0

Hayatta (bir bilgisayar programında olduğu gibi) tekrarlama nadiren doğrudan kontrolümüz altında gerçekleşir, çünkü gerçekleşmesi kafa karıştırıcı olabilir. Ayrıca, algı, işlevsel olarak saf olmaktan ziyade, yan etkileri ile ilgili olma eğilimindedir, bu nedenle özyinleme gerçekleşiyorsa bunu farketmeyebilirsiniz.

Dünyada özyineleme burada gerçekleşiyor. Çok.

İyi bir örnek, su döngüsünün (basitleştirilmiş bir versiyonudur):

  • Güneş gölü ısıtıyor
  • Su gökyüzüne gider ve bulutlar oluşturur
  • Bulutlar bir dağa doğru kayıyor
  • Dağda hava nemlerinin tutulması için çok soğuk olur
  • Yağmur yağıyor
  • Bir nehir oluşuyor
  • Nehirdeki su göle akıyor

Bu, kendini tekrar etmesine neden olan bir döngüdür. Özyinelemeli.

Özyineleme alabileceğiniz bir diğer yer ise İngilizce'dir (ve genel olarak insan dili). İlk başta tanımayabilirsiniz, ancak bir cümle üretme biçimimiz özyinelemelidir, çünkü kurallar bir sembolün bir örneğini aynı sembolün başka bir örneğine yan tarafa yerleştirmemize izin verir.

Steven Pinker'in Dil İçgüdüsünden:

ya kız dondurma yerse, ya da kız şeker yerse sonra oğlan sosisli sandviç yiyorsa

Bu, diğer tüm cümle içeren bir cümledir:

kız dondurma yiyor

kız şeker yiyor

çocuk sosisli sandviç yiyor

Tam cümleyi anlama eylemi, tam cümle olarak anlaşılması için aynı zihinsel kandırmayı kullanan daha küçük cümleleri anlamayı içerir.

Bir özyinelemeyi programlama perspektifinden anlamak, özyinelemeyle çözülebilecek bir probleme bakmak ve neden olması gerektiğini ve bunun ne anlama geldiğini anlamak en kolay yoldur.

Örneğin, en büyük ortak bölen işlevini ya da kısaca gcd'yi kullanacağım.

İki numaran var ave b. Kendi gcd'lerini bulmak için (hiçbirinin 0 olmadığını varsayarak) aeşit olarak bölünebilir olup olmadığını kontrol etmeniz gerekir b. Eğer öyleyse bgcd ise, aksi halde gcd'yi bve kalanını kontrol etmeniz gerekir a/b.

Gcd işlevini çağıran gcd işlevine sahip olduğunuzdan, bunun özyinelemeli bir işlev olduğunu görebilmelisiniz. Sadece eve çekiçlemek için, işte c # (yine, 0'ın bir parametre olarak asla geçilmediğini varsayarsak):

int gcd(int a, int b)
{   
    if (a % b == 0) //this is a stopping condition
    {
        return b;
    }

    return (gcd(b, a % b)); //the call to gcd here makes this function recursive
}

Bir programda, durma koşulunun olması önemlidir, aksi halde işleviniz sonsuza kadar tekrar eder ve sonunda yığın taşmasına neden olur!

Bir süre döngü veya başka bir yinelemeli yapı yerine, özyinelemenin burada kullanılmasının nedeni, kodu okuduğunuzda, ne yaptığını ve sonra ne olacağını söyleyeceğinden, doğru çalışıp çalışmadığını anlamak daha kolaydır. .


1
Su döngüsü örneğini yinelemeli buldum. İkinci dil örneği, özyinelemeden daha fazla bölün ve ele geçirilmiş gibi görünüyor.
Gulshan

Gülhan: Su döngüsünün özyinelemeli olduğunu söyleyebilirim, çünkü özyinelemeli bir işlev gibi kendini tekrar etmesine neden olur. Bir formadaki gibi, birkaç nesne üzerinde (duvarlar, tavan vb.) Aynı basamak setini uyguladığınız odayı boyamak gibi değildir. Dil örneği, bölme ve fethetmeyi kullanır, fakat aynı zamanda “işlev” olarak adlandırılan iç içe geçmiş cümleler üzerinde çalışmak için kendini çağırır, bu nedenle özyinelemelidir.
Matt Ellen,

Su döngüsünde, döngü güneş tarafından başlatılır ve döngünün başka hiçbir elemanı güneşi yeniden başlatmaya zorlamaz. Peki, özyinelemeli çağrı nerede?
Gulshan

Özyinelemeli bir çağrı yok! Bir işlev değil. : D Özyinelemelidir çünkü kendi kendine yinelenmesine neden olur. Gölden gelen su göle geri döner ve döngü tekrar başlar. Başka bir sistem göle su koyarsa, yinelemeli olur.
Matt Ellen,

1
Su döngüsü bir süre döngüdür. Elbette, bir süre döngü özyineleme kullanılarak ifade edilebilir, ancak bunu yapmak yığını üfleyecektir. Lütfen yapma
Brian

0

İşte özyineleme için gerçek bir dünya örneği.

Komik bir koleksiyona sahip olduklarını hayal etmelerine izin verin, hepsini büyük bir yığına karıştırın. Dikkatli olun - eğer gerçekten bir koleksiyonları varsa, bunu yapma fikrinden bahsettiğinizde sizi anında öldürebilirler.

Şimdi bu büyük sıralanmamış çizgi roman dizisini bu kılavuzun yardımıyla sıralamasına izin verin:

Manual: How to sort a pile of comics

Check the pile if it is already sorted. If it is, then done.

As long as there are comics in the pile, put each one on another pile, 
ordered from left to right in ascending order:

    If your current pile contains different comics, pile them by comic.
    If not and your current pile contains different years, pile them by year.
    If not and your current pile contains different tenth digits, pile them 
    by this digit: Issue 1 to 9, 10 to 19, and so on.
    If not then "pile" them by issue number.

Refer to the "Manual: How to sort a pile of comics" to separately sort each
of the new piles.

Collect the piles back to a big pile from left to right.

Done.

Buradaki iyi şey şudur: Tek meselelere düştüğünde, yerel yığınları tam yerde durmadan "yığın çerçeveye" sahiptirler. Onlara el kitabının birçok çıktısını verin ve şu anda bulunduğunuz yerde (yani yerel değişkenlerin durumu) bir işaret ile her bir yığın düzeyini bir kenara koyun, böylece her bir Done üzerinde devam edebilirsiniz.

Temelde özyinelemenin konusu budur: Aynı işlemi gerçekleştirmek, daha ince bir detay düzeyinde, daha fazla işin içine girmek.


-1
  • Çıkış durumuna ulaşılırsa sonlandır
  • durumlarını değiştirmek için bir şeyler yap
  • İşleri baştan sona mevcut durumdan başlayarak yapın

Özyineleme, bir şeye ulaşılıncaya kadar tekrarlanması gereken bir şeyi ifade etmenin çok özlü bir yoludur.



-2

Özyinelemenin güzel bir açıklaması tam anlamıyla 'kendi içinden tekrarlanan bir eylemdir'.

Duvara boyayan bir ressam düşünün, bu özyineldir, çünkü hareket "tavandan zemine doğru bir şeridi biraz sağa doğru boyamak ve (tavandan zemine doğru bir şerit boyamak biraz sağa doğru boyamak ve tavandan zemine doğru sola, biraz sağa kaydırın ve (vb))) ".

Paint () işlevi, daha büyük paint_wall () işlevini oluşturmak için kendini tekrar tekrar çağırır.

Umarım bu zavallı ressam bir tür durma durumuna sahiptir :)


6
Bana göre, örnek özyinelemeli değil, yinelemeli bir prosedür gibi görünüyor.
Gulshan

@Gulshan: Özyineleme ve yineleme benzer şeyler yapar ve çoğu zaman işler de ya iyi sonuç verir. İşlevsel diller genellikle yineleme yerine özyinelemeyi kullanır. Aynı şeyi yinelemeli olarak yazmanın zor olacağı daha iyi özyineleme örnekleri vardır.
David Thornley,
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.