Ö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?
Ö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?
Yanıtlar:
Açıklamak için Özyinelemeyi , genellikle her iki denemek için farklı bir açıklama bir arada kullanın:
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.
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.
Genellikle, ya en iyi ihtimalle bir "ha ha, ne" "elde edersin, çünkü hala kullanmıyorlar, ya da muhtemelen çok derin bir horlama.
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, write
veya 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:
Ç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.
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:
yinelenme ile böyle ifade edilebilir:
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.
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:
Karşılıklı özyinelemeli:
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 .
İ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 n
ya 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 n
ve 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 h
ve l
sadece ş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 :
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 .
static unsigned int vote = 1;
, benden bir alır . Statik mizahı affet, eğer istersen :) Bu, şu ana kadarki en iyi cevap.
Aynı işlevin içindeki bir işlevin çağrılması.
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.
a
hala dolaylı olarak (çağırarak b
) kendisini çağırır .
Özyinelemeli programlama, kendi sürümlerini çözmeyi kolaylaştıracak bir sorunu aşamalı olarak azaltma sürecidir.
Her özyinelemeli işlev eğilimindedir:
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.
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:
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?
Tamam, bu basit ve özlü tutmaya çalışacağım.
Özyinelemeli işlev kendilerini çağıran işlevlerdir. Özyinelemeli işlevi üç şeyden oluşur:
Ö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.
Ö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.
Bunu kullanmayı seviyorum:
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:
Aslında özyinelemeyi günlük yaşamda çok kullanıyoruz; biz sadece böyle düşünmüyoruz.
for
döngüyü anlamsız özyinelemeli bir işleve dönüştürmeye eşdeğer olduğunu düşünüyorum .
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.
Ö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ı:
Dezavantajları:
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.
Ö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
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):
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 a
ve b
. Kendi gcd'lerini bulmak için (hiçbirinin 0 olmadığını varsayarak) a
eşit olarak bölünebilir olup olmadığını kontrol etmeniz gerekir b
. Eğer öyleyse b
gcd ise, aksi halde gcd'yi b
ve 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. .
İş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.
Sade ingilizce değil, gerçek hayattan örnekler değil, oynayarak yinelemeyi öğrenmenin iki yolu:
Ö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 :)