Özyineleme - “böl ve fethet” veya “kodun yeniden kullanımı”


11

Özyineleme - hepimizin bildiği gibi - bu sorunlardan biridir - kafanızı sarmak, programlama yolculuğunuzda bir "kilometre taşı" elde etmek gibi hissettirir.

Ancak, gerçek dünya problemlerinde bunu kullanmak söz konusu olduğunda - özyineleme mekaniğini bilmek yeterli DEĞİLDİR - özyineleme en uygun çözümün olduğu problemlerin doğasını da anlamak gerekir.

İşte benim sorum bu...

  • özyineleme çözümünü gerektiren "sorun modelleri" nelerdir
  • özyineleme bir "böl ve fethet" stratejisi veya "kodun yeniden kullanımı" biçimidir - ya da kendi başına bir tasarım modelidir
  • bize özyinelemenin akılcı bir çözüm olarak akla geldiği gerçek dünya sorununa bir örnek verebilir misiniz?

-- GÜNCELLEME --

cevaplar bir sürü "gerçek sorunları" ağaç gezici, faktöriyel, vb atıfta bulunmaktadır. "GERÇEK gerçek sorunları" tercih ediyorum - size bir örnek vereyim ...

BÜYÜK bir metin mandreni (bağlantılı bir liste olarak yaklaşık 30 MB metin structs) vardı ve tam metin araması için bir dizin oluşturmamız gerekiyordu. Dizinin tamamını bellekte tutmamız ve metni her 10 dakikada bir yeniden dizine eklememiz gerekiyordu.

Her 10 dakikada bir, metnin tamamını (iki bağlantılı liste, satır satır) yeni oluşturulan bir metin grubuyla karşılaştırırdık - hangi satırın değiştiğini görmek için - ve sonra yalnızca bu satırı yeniden dizine eklerdik - bu şekilde ENTIRE metnini yeniden endekslemek zorunda kalmazdık. Unutmayın - iki 30 MB bağlantılı liste arasındaki fark noktalarını bulmamız gerekiyordu.

Meslektaşlarımdan biri, hatları karşılaştırmak için AĞIR özyineleme kullanılan ve daha sonra aynaların bir dizide farklı olduğu yerleri toplayan harika bir program buldu - evet, şaşırtıcı geldiğini biliyorum - özyineleme burada nasıl yardımcı olabilir - ama o yaptı.

Mesele şu ki - bu sorunun ağır özyineleme kullanımı ile akıllıca çözülebileceğini nasıl görebilir?


Çoğu bilgisayarın GB RAM ve TB sabit disk alanına sahip olduğu günümüzde 30 MB gerçekten büyük mü?
JB King

30 MB büyük olmayabilir - ancak metnimizin sıkıştığı veri yapısı göz önüne alındığında - gerçekten PROSES ve DIFF için BÜYÜK metin mandreni idi.
treecoder

3
“Bir klasör yapısını gezmek” yeterince GERÇEK değil mi? Ve örneğinizde, burada özyinelemenin nasıl sezgisel olmaması ve kullanımının neden özellikle dikkate değer olması gerektiğini tamamen göremiyorum. İş arkadaşınız, tıpkı diğer algoritmalar gibi, özyinelemeli bir algoritma tasarladı. Hoare'in sıralama problemini özyinelemeli olarak nasıl çözdüğü fikrini de sorabilirsiniz.
Konrad Rudolph

2
"Kod tekrar kullanımı" demek istediğinizi, "aynı işlem dizisini belirsiz sayıda yürütmek" demek istediğimi düşünüyor muyum? Bu, başka bir yerde kullanmak için genel kod yazma anlamında "kodun yeniden kullanılması" nın aksine.
Andy Hunt

4
Ancak ağaç geçişi, birçok insanın neredeyse günlük olarak karşılaştığı "GERÇEK gerçek bir sorundur".
Falcon

Yanıtlar:


16
  • özyineleme çözümünü gerektiren "sorun modelleri" nelerdir

Özyineleme kullanımı için bir sorun modeli gibi bir şey olduğunu söyleyemem. Özyineleme ile uygulanabilecek her işlev, genellikle bir yığını iterek ve patlatarak da yinelemeli olarak uygulanabilir.

Bu bir ifade meselesi ve aynı zamanda bir performans meselesi. Yinelemeli algoritmalar genellikle daha iyi bir performansa sahiptir ve optimize edilmesi daha kolaydır. Bununla birlikte, özyinelemeli algoritmalar daha açık bir ifadeden yararlanır ve bu nedenle okunması, anlaşılması ve uygulanması genellikle daha kolaydır.

Hatta bazı şeyler özyineleme olmadan ifade edilemez, örneğin sonsuz listeler. İşlevsel diller olarak adlandırılan diller, doğal ifade biçimleri olduğu için özyinelemeye büyük ölçüde güvenir. "Özyinelemeli programlama doğru yapılan fonksiyonel programlamadır".

  • özyineleme bir "böl ve fethet" stratejisi veya "kodun yeniden kullanımı" biçimidir - ya da kendi başına bir tasarım modelidir

Buna tasarım deseni demezdim. Bu bir ifade meselesi. Bazen özyinelemeli bir ifade daha güçlü ve daha ifade edicidir ve bu nedenle daha iyi ve daha temiz kodlara yol açar.

  • bize özyinelemenin akılcı bir çözüm olarak akla geldiği gerçek dünya sorununa bir örnek verebilir misiniz?

Ağaçları geçmesi gereken her şey, özyinelemeli bir algoritma ile düzgün bir şekilde ifade edilecektir.


7
"Özyineleme ile uygulanabilecek her işlev, genellikle bir yığının itilmesi ve patlatılması yoluyla yinelemeli olarak da uygulanabilir." Sonuçta, yığın tabanlı bellek kullanan dillerde, özyineleme kullanırken işlev verilerini zaten yığının içine itip açıyorsunuz.
JAB

Yalnızca dili bir makine ile derlerseniz veya yorumlarsanız ;-) Ayrıca, çok yüksek bir bakış açısından, ifade ve dil, makine ve donanım ve işletim sisteminden tamamen bağımsızdır, bu nedenle, bir yığın olması gerekmez.
Falcon

Ah, evet, kesinlikle haklısın. "Yığın tabanlı bellek kullanan dil / dil derleyicilerinin uygulamalarında" demeliydim.
JAB

Genel olarak konuşursak, sen de haklısın. Nitpick görünmek istemedim.
Falcon

2
Sonsuz listeler özyineleme olmadan, en azından özyinelemeli bir uygulama olmadan ifade edilebilir . Python jeneratörleri bunu yapabilir, tıpkı Icon'daki Python'un fikri ödünç aldığı jeneratörler gibi. Emin değilim F # bu hile yapabilir inanıyorum. Temel olarak, jeneratörler tembel listelerin uygulanması için çok uygun olan özel bir ko-rutin durumudur (kooperatif çoklu görev gibi). Bir jeneratör her "sonuç" verdiğinde, arayan kontrolü tekrar kazanır ve bir sonraki sonuç talep edilene kadar jeneratör boşta kalır.
Steve314

8

özyineleme bir "böl ve fethet" stratejisi veya "kodun yeniden kullanımı" biçimidir - ya da kendi başına bir tasarım modelidir

Ne. Böl ve fethet , özyineleme kullanır . Ancak özyineleme her zaman bölmek ve fethetmek değildir, çünkü ikincisi bir problemi iki (veya daha fazla) parçaya bölmek ve her birini simetrik olarak çözmek anlamına gelir. Özyinelemede, bunu yapmazsınız.

Kodun yeniden kullanımı tamamen ilişkisizdir ve bir tasarım modeli çok daha yüksek bir seviyede devreye girer. Örneğin, böl ve fethet (hatta özyinelemeden daha üst düzey bir desen) bile hala bir tasarım deseni olarak kabul edilmez - aksine, algoritmik bir desendir.

bize özyinelemenin akılcı bir çözüm olarak akla geldiği gerçek dünya sorununa bir örnek verebilir misiniz?

Ağaç geçişi. Veya daha genel olarak grafik geçişi. Bu özellikle bir klasör yapısının çapraz geçişini içerir.

Ve elbette böl ve fethet veya dinamik programlama kullanan her şey doğal olarak özyineleme olarak ifade edilir.


Dinamik programlama her zaman doğal olarak özyineleme olarak ifade edilmez. Aslında, dinamik programlama kesinlikle tablolama yaklaşımlarını ifade eder - notlaşma hariç. Bu konuda görüşler değişiyor gibi görünüyor, ancak "dinamik programlama" daki "programlama" aslında bir tabirsel yaklaşımlara (MIT açık yazılım algoritmaları dersinden aldığım bir trivia parçası) atıfta bulunan bir matematik terimidir. Dolayısıyla, dinamik programlama, en basit şekilde basit bir döngü olarak ifade edileni kullanarak en uygun altyapıyı kullanır. Memoizasyonun özyineleme anlamına gelmesi çok daha olasıdır, ancak zorunlu olarak değil.
Steve314

1
@ Steve314 DP'nin pratik uygulamasının (bir bilgisayar programında veya manuel olarak) nadiren özyineleme kullandığını kabul ediyorum. Ancak fikir doğası gereği bir nüks ilişkisine dayanır - bu sadece özyinelemeli bir formüldür! - ve bir taban kasa.
Konrad Rudolph

"En uygun alt yapının" (en iyi çözümün en iyi kısmi çözümlere sahip olduğu) yinelemeli bir fikir olduğunu kabul ediyorum. Bu, doğrudan uygulama ile ilgili olmayan, özyinelemenin bir matematik / bilgisayar bilimi görüşüdür - ancak özyinelemenin bilgisayar bilimindeki rolü, önemli bir noktadır. Az sayıda algoritma (ve muhtemelen tasarım deseni yok) bilgisayar biliminde önemli araçlardır - çoğu, başka bir şeyi incelemek için kullanılacak araçlardan ziyade yalnızca incelenecek konulardır.
Steve314

4
what are the "problem patterns" that call for the solution of recursion

Fraktalların öz-benzerliklerinden türetilen, öz-eşitlik veya öz-kimlik (veya buna rağmen denir) özyineleme için tipik bir sorun modeli olduğunu söyleyebilirim. Yani bir problem, ana problemle aynı yapıya sahip alt problemlere ayrılabilir.

Bahsedilen ağaç dolaşımında, her alt ağaç, tıpkı ana ağaç gibi kendi içinde tam bir ağaçtır ve ana ağaç başka bir ağaç içindeki bir alt ağaç olabilir.

Sanırım meslektaşınız indeksleme probleminizin öz-eşitlik özelliklerini keşfetti. Ya da tam tersine döndü ve problemi öz-eşit bir temsile dönüştürdü.


1
+1 "bir sorun, ana sorunla aynı yapıya sahip alt sorunlara
bölünebilir

+1 ve açıklamak için: problemin çözümü alt katmanlar için geçerlidir. Gerçek dünyadaki örneğim, "toplu iş" e katkıda bulunan kredi kartı ücretleri bulmak. Muhasebe yazılımı, bireysel ücretlere ve toplu çeke çek hesabına sahip olacaktır. Benim durumum burada bir soru haline gelebilir çünkü stackoverflow bu konuda çok keskin değildi. stackoverflow.com/questions/14719806
Chris K

3

Peki, zorunlu döngüleri fonksiyonel fonksiyonlara dönüştürmeye çalışacaksa özyineleme kolayca anlaşılabilir. Her neyse, tüm sorulara cevap vermeye çalışalım:

özyineleme çözümünü gerektiren "sorun modelleri" nelerdir

Ağaç benzeri bir yapınız veya algoritmanız varsa, özyinelemeye ihtiyacınız olacaktır. Zorunlu kodunuz bir yığınla ilgiliyse, özyineleme yapmanız gerekir. Algoritmanızdaki belirli bir adım önceki adımlara (düşünme döngüleri) bağlıysa, özyinelemeye ihtiyacınız vardır. Burada ihtiyaç olabildiğince yorumlanmalıdır.

özyineleme bir "böl ve fethet" stratejisi veya "kodun yeniden kullanımı" biçimidir - ya da kendi başına bir tasarım modelidir

Yok. Böl ve fethet, özyineleme kullanır, ancak yığınlarla uygulanabilir. Kodun yeniden kullanımı başka bir şeye işaret eder. Tasarım kalıpları basit özyinelemeden daha karmaşıktır.

bize özyinelemenin akılcı bir çözüm olarak akla geldiği gerçek dünya sorununa bir örnek verebilir misiniz?

Ayrıştırma ve ağaç yapıları ile ilgili her şey. Örtük ağaç yapıları bile.


3

Kolaylaştırmak için basitleştirmenin bir yolu varsa, özyinelemenin işe yarayabileceği ipucu olabilir. Sen sürebilir sıralama ve benzeri özyinelemeli çözümler var orada yapmak örnekler ararken Birleştirme Sıralama ve İkili Arama sırasıyla.

Akılda tutulması gereken bir şey, bir faktöriyel gibi özyineleme ile bazı sorunların nasıl zayıf bir şekilde çözülebileceğidir.

Özyinelemeyi kullanacağım gerçek bir dünya örneğine gelince, kitap rafından bir kitap aramak özyinelemeli bir şekilde kolayca yapılabilir. Sadece kitaba bakıyorum ve eğer istediğim bu değilse bir sonrakine geçiyorum. Kitabı bulduğumda veya satırın sonuna geldiğimde duruyorum. Bir kitabı kontrol etme ve bir sonrakine geçme döngüsü yinelemeli olarak yapılabilir. Belki de bu bir örnek için çok gerçektir.


2

özyineleme çözümünü gerektiren "sorun modelleri" nelerdir

Çok genel terimlerle, f (x) = f (g (x)) olduğu bir sorunu çözerken özyineleme çağrılır . Sonsuz özyineleme ile iyi değilseniz, g (x) x olarak değerlendirmemelidir .

özyineleme bir "böl ve fethet" stratejisi veya "kodun yeniden kullanımı" biçimidir - ya da kendi başına bir tasarım modelidir

Yukarıdakilerin hiçbiri. Aynı şeyi tekrar tekrar yapmanın bir yolu, bazen girişteki varyasyonlara dayanarak. Konsept, tasarım desenlerinden, kodun yeniden kullanılmasından ve hatta bilgisayarlardan çok daha uzun süredir.

bize özyinelemenin akılcı bir çözüm olarak akla geldiği gerçek dünya sorununa bir örnek verebilir misiniz?

Faktöriyeller, Fibonacci dizisi, ağaç geçişi ve diğer birçok problem, nüks ile çözülebilir. Kendini çağıran bir işlev anlamında özyineleme, bu tür şeyleri uygulamanın en iyi yolu olmak zorunda değildir ; aynı etkiyi elde etmenin başka yolları da vardır (örneğin, bir yığın ve döngü).


-1

Özyinelemeli bir algoritma yazdığınızda, genellikle sorunun özyinelemeli bir tanımını koda çevirirsiniz. O zaman nasıl yürütüleceğini bilmenize bile gerek yok .

Fonksiyonel programlamada olan budur. Aslında, nasıl (tanım) değil, nasıl tanımlandığını belirtirsiniz . Başka bir deyişle, tabanı tanımlar ve ardından sorununuzu bir alt sorun teriminde tanımlarsınız.

Örneğin Factorialalgoritmayı düşünün

  • Tabanı tanımlayın: Faktöriyel (1) = 1;
  • Faktöriyel n'yi tanımlayın: Faktöriyel (n) = n * Faktöriyel (n-1);

O zaman bir sorunla karşılaştığınızda, onu tekrar tekrar tanımlayıp tanımlayamayacağınızı, tekrarlı olarak tanımlayabiliyorsanız, neredeyse çözdüğünüzü düşünmelisiniz.

Ancak, yinelemeli işlevler yinelemeli bir tanım olmamalıdır. Ana problemi tanımlayabilir ve ana problemin çözümünü alt problemlerin çözümü (tanım) ile ilişkilendirebilirsiniz. Ancak bu ilişki için bir prosedüre ihtiyacınız olabilir.

Bir örnek MergeSortburada mergetanımı ya da alt dizilerin tür tüm dizi sıralama çözeltisi ilgili bir zorunluluk prosedür olabilir.

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.