Tüm özyinelemeli işlevler yinelemelerle kodlanabilir mi? [kapalı]


10

Özyinelemenin avantajları nelerdir?

Bazı programlama dilleri kuyruk yinelemesini optimize edebilir, ancak yine de genel olarak, yineleme normal döngülerden daha fazla kaynak tüketir.

Bazı özyinelemeli işlevlerin yinelemeli bir sürümüne sahip olmak mümkün müdür?



Yanıtlar:


10

Evet, yinelemeli işlevleri yineleme olarak kodlayabilirsiniz. Temel olarak, derleyici tarafından oluşturulan yöntem çağırma kodu tarafından halledilecek bilgileri manuel olarak korumanızı gerektirir.

Başka bir deyişle, her girdinin geçirilen parametreleri ve tüm yerel değişkenleri içeren bir yapı olduğu bir yığına ihtiyacınız vardır. Her zaman yığının en üstündeki girişte çalışırsınız. Kendinizi aramanız gerekirse, yeni bir giriş oluşturun ve yığının üstüne koyun. İşiniz bittiğinde, yığının en üstteki girişini aşağıda gösterilen değeri alın ve dönüş değerlerini ayıklamak ve en üstteki yeni girişi buna göre güncellemek için en üstteki girişi kullanın.

Bunun genellikle makine kodunda nasıl uygulandığını görmek için bir derleyici kitap incelemenizi öneririz.


Anladım. Peki, özyinelemenin ne gibi bir avantajı olurdu? Basitlik?
OscarRyz

2
@OscarRyz: Evet ve daha zarif.
Michael K

@OscarRyz, ben tarif ettik yolu olduğunu tekrarlama. Sadece yerel CPU talimatları ile yapılmaz. Manuel olarak yapmak, yerel talimatlarla kötü bir şekilde eşleşen paralelleştirme gibi şeyleri yapmanızı sağlar.

15

Özyineleme, şeylere yinelemekten daha doğal bir bakış açısıdır. Örneğin, bir ikili ağacın düzensiz geçişini düşünün: inorder(left); process(); inorder(right);bir yığını açıkça korumaktan çok daha basittir.

Çok derine inmediğiniz sürece (yığını üfleme), kaynak kullanımındaki fark genellikle önemsizdir. Genel olarak endişelenme. Basit kod normalde elle optimize edilmiş koddan daha iyidir, ancak istisnalar vardır. Doğru normalde hızlı olmaktan iyidir.

Herhangi bir özyinelemeli algoritma yinelemeli bir algoritma olarak ifade edilebilir, ancak açık bir yığın tutmanız gerekebilir (örtük olarak işlenen çağrı yığınına karşılık gelir). Sonuçta, özyinelemeli bir işlevi derlerseniz, bir yığını manipüle etmeye ve işlev boyunca döngü yapmaya dayanan bir şey elde edersiniz ve bu yinelemelidir.

Kuyruk özyinelemeli işlevler kolayca döngülere dönüştürülebilir ve bir yığına gerek yoktur, ancak bu özel bir durumdur.


8
Diyorum ki doğru daima hızlı olmaktan iyidir. Yanlış şeyi çok hızlı yapan kod kimseye pek iyi gelmez.
Mason Wheeler

1
Peki ya bu yanlış şeyi gerçekten hızlı bir şekilde yapabilirseniz ?!
RationalGeek

1
@jkohlhepp - Herhangi bir sorunu anında çözebilirim. Cevap 0
Kendine not -

2
Açık bir yığın yerine özyineleme kullanmak daha verimli olabilir; yığın ayırma gereksinimi, olası bellek parçalanması ve olası konum sorunları önlenir. Ancak, "sağ normalde hızlıdan daha iyidir" durumunda, yazılımınızın işlemesi gereken durumlarda yığın taşması kodunuzun bozulduğu anlamına gelir. Genellikle, sorun vakalarını tespit etmek oldukça kolaydır - (makul) dengeli bir ağaçta özyineleme iyidir, ancak çok dengesiz olabilen veya bağlantılı bir listede bir ağaçta özyineleme C gibi bir dilde ciddi bir hata olabilir. , basit testlerden kurtulabilir ve yalnızca gerçek olarak konuşlandırıldığında çökebilir.
Steve314

1
Sanırım hepiniz Mason'un ne anlama geldiğini anlıyorsunuz ve sadece eğlenmek için şakalar yapıyorsunuz. Elbette yavaş ve doğru bir program hızlı bir yanlış programdan daha kullanışlıdır.
Giorgio

4

Özyinelemenin avantajları nelerdir?

Hanoi Kuleleri problemini tekrar tekrar çözmeye çalışın. Vazgeçtikten sonra, yinelemeli çözüme bir göz atın ve özyinelemeli çözümle karşılaştırın. Hangisi daha basit?

Bazı özyinelemeli işlevlerin yinelemeli bir sürümüne sahip olmak mümkün müdür?

Evet, prensipte. Bununla birlikte, ağaç geçişleri gibi çok yaygın görevler de dahil olmak üzere birçok sorun için, özyinelemeli çözümler yinelemeli çözümlerden çok daha basit ve daha zariftir.


3

Özyinelemenin avantajları nelerdir?

Basitlik. Kuyruk çağrısı optimizasyonu olmadan elbette daha fazla kaynak (yığın) alır, ancak deltreeJava'da özyineleme olmadan nasıl uygularsınız ? Büküm, delete()dizinleri yalnızca boş olduklarında silebilmesidir; İşte özyineleme ile:

deltree(File fileOrDirectory) {
    if (fileOrDirectory.isDirectory()) {
        for (File subFileOrDirectory : fileOrDirectory.listFiles()) {
            deltree(subFileOrDirectory);
        }
    }
    fileOrDirectory.delete();
}

1
Diğer cevaplarda belirtildiği gibi bir yığınla.
Nicole

Evet, ama bu ne kadar basit? -)
Joonas Pulakka

Oh, özyineleme kesinlikle daha iyi. Bunun mümkün olmadığını söylediğini sanıyordum.
Nicole

0

Özyinelemenin bir programcının yaşamak zorunda olduğu araçlardan biri olduğuna inanıyorum . Özyineleme ile algoritmalarınızı "düşünebilir" ve tam da bunu düşündüğünüz gibi çözebilirsiniz. Ama, sizi uyarmalıyım, herkes özyinelemenin ne kadar güzel olduğundan ve koda ne kadar basitlik getirdiğinden bahsediyor, söyleyecek birkaç şeyim var:

  1. Her şeyden önce, bir algoritmanın "özyinelemeli yolunu" düşünmek kolay değildir. Faktöriyel (n!) Veya Hanoi Kuleleri gibi bir şey inşa etmek buzdağının sadece görünen kısmıdır ve dibe ulaşmak bir tuvalet zamanı gerektirir.
  2. Özyinelemenin yalnızca kodunuza basitlik getirdiğini düşünmeyin, bazen yinelemeli yol çirkin ve dağınıktır, ancak maliyet etkindir (Fibonacci sorununun özyinelemeli çözümüne bakın)

Bunları göz önünde bulundurarak, özyineleme öğrenin! komik, karmaşık ve beynini parçalayacak! ama kendini sevdiğini göreceksin.

İyi şanslar!

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.