Bir sorunu çözmek için özyineleme kullanıp kullanamayacağınızı belirlemek için dikkat edilmesi gereken noktalar nelerdir?


10

Bazen görüşmelerde, bir sorunu çözmek için özyineleme kullanabilirim ( 1sonsuz bir kesinlik tamsayı eklemek gibi ) veya sorun kendini özyinelemeyi kullanmaya uygun gösterdiğinde. Bazen, problemi çözmek için özyinelemenin çok fazla kullanılmasından kaynaklanabilir, bu yüzden fazla düşünmeden, sorunu çözmek için özyineleme kullanılır.

Ancak, bir sorunu çözmek için özyineleme kullanmanın uygun olduğuna karar vermeden önce dikkat etmeniz gereken noktalar nelerdir?


Bazı düşüncelerim vardı:

Her seferinde yarıya indirilen verilerde özyineleme kullanırsak, 16GB RAM'e veya hatta 8 TB'lık bir sabit diske sığabilecek tüm veriler sadece 42 seviye derinlikte özümleme ile işlenebildiğinden özyineleme kullanmanın bir sorun olmadığı görülüyor. (yani yığın taşması yok (bence bazı ortamda, yığın 4000 seviye derinliğinde, 42'den fazla olabilir, ancak aynı zamanda, her çağrı yığını olarak daha fazla bellek kapladığı kaç yerel değişkene bağlıdır. çok sayıda yerel değişken varsa ve yığın taşmasını belirleyen düzey değil, bellek boyutudur)).

Saf özyineleme kullanarak Fibonacci sayılarını hesaplarsanız, ara sonuçları önbelleğe almadığınız sürece gerçekten zaman karmaşıklığı konusunda endişelenmeniz gerekir.

Ve 1sonsuz bir hassas tamsayıya eklemeye ne dersiniz ? Belki de 3000 basamak uzunluğunda veya 4000 basamak uzunluğundaki rakamlarla çalışacaksınız, o kadar büyük ki, yığın taşmasına neden olabilir mi? Bunu düşünmedim, ama belki cevap hayır, özyineleme kullanmamalıyız, ama sadece düz bir döngü kullanmalıyız, çünkü bazı uygulamalarda, sayı gerçekten 4000 basamak uzunluğundaysa, bazılarını kontrol etmek için sayının asal olup olmadığı gibi sayının özellikleri.

Nihai soru şudur: Bir sorunu çözmek için özyineleme kullanmaya karar vermeden önce dikkat etmeniz gereken noktalar nelerdir?


7
Aslında oldukça basit: "Biraz daha küçük bir sorunun çözümünün bilindiğini varsayabilirsem çözüm önemsiz mi?"
Kilian Foth

Peki ya Fibonacci sayısı ya da 1sonsuz hassas tamsayıya ekleme ? Evet, daha küçük bir probleme indirgenebilirler, ancak saf özyineleme bunun için uygun değildir
nonopolarite

Bunu faydalı bulabilirsiniz - stackoverflow.com/questions/3021/…
Kishor Kundan

Yanıtlar:


15

Göz önünde bulundurulması gereken noktalardan biri, algoritmanızın soyut bir çözüm mü yoksa pratik bir yürütülebilir çözüm mü olup olmadığıdır. Önceki durumda, aradığınız özellikler doğruluktur ve hedef kitleniz 1 için kolay anlaşılırlıktır . İkinci durumda, performans da bir sorundur. Bu hususlar seçiminizi etkileyebilir.

İkinci bir husus (pratik bir çözüm için) kullandığınız programlama dilinin (ya da daha doğrusu, uygulanmasının) kuyruk çağrısının ortadan kaldırılması mıdır? Kuyruk çağrısı eliminasyonu olmadan, özyineleme yinelemeden daha yavaştır ve derin özyineleme yığın taşması sorunlarına yol açabilir.

(Doğru) özyinelemeli bir çözümün eşdeğer özyinelemeli olmayan bir çözüme dönüştürülebileceğini unutmayın , bu nedenle iki yaklaşım arasında zor bir seçim yapmanız gerekmez.

Son olarak, bazen özyinelemeli ve özyinelemesiz formülasyonlar arasındaki seçim, bir algoritma hakkındaki özellikleri (resmi anlamda) kanıtlama ihtiyacı ile motive edilir. Özyinelemeli formülasyonlar daha doğrudan indüksiyonla kanıtlamaya izin verir.


1 - Bu , hedef kitlenin ... ve buna pratik kodu okuyan programcıların ... dahil edilmesi gibi hususları içerir , bir çözüm stilini diğerinden "daha doğal" olarak görür. "Doğal" kavramı, programlama veya algoritmaları nasıl öğrendiklerine bağlı olarak kişiden kişiye değişecektir. (Aynı "doğallık" önermektedir ben meydan kimse birincil kullanım özyineleme karar (ya da değil kriterlerine) nesnel anlamda "doğallık" tanımlamak; yani bunu ölçmek nasıl.)


2
Bazı problemler özyineleme kullanılarak daha doğal olarak ifade edilir. Örneğin, ağaç geçişi.
Frank Hileman

Cevabımı bu
Stephen C

1
"Doğallık" ile ilgili olarak: örneğin, özyineleme olmadan ağaçta gezinme, daha büyük, daha az genel amaçlı kod üretme eğilimindedir. Örneğin, yaprak ve kompozit düğümler için farklı davranışlarla ağacı hareket ettirmek için polimorfik çağrılar kullanmayı düşünün. Bu özyineleme olmadan mümkün değildir.
Frank Hileman

1) Henüz "doğal" ı tanımlamak için uğraştım mı? 2) Yığın veri yapısı kullanarak özyinelemeyi simüle etmek mümkün olduğu için, ağaç geçişini de bu şekilde uygulamak mümkündür. En etkili yol olmayabilir ... ve size en okunabilir kodu vermeyecektir ... ancak bunu yapmak kesinlikle mümkündür ve pratiktir.
Stephen C

Bu arada, öğrendiğim ilk programlama dili (FORTRAN 4) özyinelemeyi hiç desteklemedi.
Stephen C

1

Bir C / C ++ programcısı olarak, en önemli düşüncem performans. Karar verme sürecim şöyle:

  1. Çağrı yığınının maksimum derinliği nedir? Çok derinse, özyineden kurtulun. Sığsa, 2'ye gidin.

  2. Bu işlevin programımın tıkanıklığı olması muhtemel mi? Evet ise, 3'e gidin. Hayır ise, özyinelemeyi koruyun. Emin değilseniz bir profil oluşturucu çalıştırın.

  3. Özyinelemeli işlev çağrıları için harcanan CPU zamanının oranı nedir? İşlev çağrıları, işlev gövdesinin geri kalanından önemli ölçüde daha az zaman alırsa, özyineleme kullanmakta sorun yoktur.


0

Ancak, bir sorunu çözmek için özyineleme kullanmanın uygun olduğuna karar vermeden önce dikkat etmeniz gereken noktalar nelerdir?

Şemada işlevler yazarken, fazla düşünmeden kuyruk yinelemeli işlevler yazmanın doğal olduğunu düşünüyorum.

C ++ 'da işlev yazarken, özyinelemeli bir işlevi kullanmadan önce kendimi tartışırken buluyorum. Kendime sorduğum sorular:

  • Hesaplama yinelemeli bir algoritma kullanılarak yapılabilir mi? Evetse, yinelemeli bir yaklaşım kullanın.

  • Özyineleme derinliği modelin boyutuna göre büyüyebilir mi? Kısa bir süre önce, modelin büyüklüğü nedeniyle özyineleme derinliğinin neredeyse 13000'e çıktığı bir davaya girdim. Acele sonrası yinelemeli bir algoritma kullanmak için işlevi dönüştürmek zorunda kaldım.

    Bu nedenle, özyinelemeli işlevler kullanarak bir ağaç geçiş algoritması yazmanızı önermem. Ağacın çalışma zamanı ortamınız için ne zaman çok derinleştiğini asla bilemezsiniz.

  • Fonksiyon, yinelemeli bir algoritma kullanılarak çok kıvrılabilir mi? Evetse, özyinelemeli bir işlev kullanın. qsortYinelemeli bir yaklaşım kullanarak yazmayı denemedim ama özyinelemeli bir işlev kullanmak onun için daha doğal bir his var.


0

Fibonacci sayıları için, saf "özyineleme" tamamen aptaldır. Çünkü aynı alt problemin tekrar tekrar çözülmesine yol açar.

Aslında, özyinelemenin çok verimli olduğu Fibonacci sayılarında önemsiz bir varyasyon vardır: n ≥ 1 sayısı verildiğinde, hem fib (n) hem de fib (n-1) hesaplayın. Yani iki sonuç döndüren bir fonksiyona ihtiyacınız var , bu fonksiyona fib2 diyelim.

Uygulama oldukça basit:

function fib2 (n) -> (fibn, fibnm1) {
    if n ≤ 1 { return (1, 1) }
    let (fibn, fibnm1) = fib2 (n-1)
    return (fibn + fibnm1, fibn)
}

programı ortak bir dilde yazabileceğinizi düşünüyor musunuz? ve fib2bir çift sayı döndürür ve bir sayı verildiğinde bir sayı döndüren fib2()arayüzüne uymaz fib(). Görünüşe göre fib(n)geri dönmek için fib2(n)[0]ama lütfen açık olun
nonopolarity 5:17
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.