Özyineleme
Bilgisayar ve Programlamaya Giriş
Temel durumÇağrıYığınVerimlilikBellekleme
Sercan KÜLCÜ · Giresun ÜniversitesiGiriş
Öğrenme Çıktıları
Yapı
Temel durum ve özyinelemeli adımı belirlemek.
İzleme
Çağrı yığınını adım adım takip etmek.
Karşılaştırma
Özyineleme ile döngüyü değerlendirmek.
İyileştirme
Tekrarlı hesaplamayı memoization ile azaltmak.
Temeller
Özyineleme Nedir?
- Bir metodun problemi daha küçük örneğe indirerek kendisini çağırmasıdır.
- Her çağrı kendi parametre ve yerel değişkenleriyle ayrı yığın çerçevesi oluşturur.
- Problem temel duruma doğru ilerlemiyorsa çağrılar sonlanmaz.
Temeller
İki Zorunlu Parça
Temel durum
Sonucun doğrudan bilindiği ve yeni çağrı yapılmayan durum.
Özyinelemeli adım
Problemi daha küçük veya daha basit örneğe dönüştüren çağrı.
Örnekler
Özyinelemeli Faktöriyel
static long faktöriyel(int n) {
if (n < 0) throw new IllegalArgumentException();
if (n <= 1) return 1;
return n * faktöriyel(n - 1);
}- Temel durum n ≤ 1'dir.
- Her çağrıda n bir azalır.
Çağrı Yığını
faktöriyel(4) Çağrıları
f(4)
4 × f(3)
4 × 3 × f(2)
4 × 3 × 2 × f(1)
24
- Çağrılar temel duruma ulaşıncaya kadar yığında açılır.
- f(1) değeri döndükten sonra çarpımlar ters sırada tamamlanır.
Örnekler
1’den n’e Toplam
static int toplam(int n) {
if (n <= 0) return 0;
return n + toplam(n - 1);
}- Tanım: toplam(n) = n + toplam(n-1).
- Temel değer: toplam(0) = 0.
Örnekler
Rakamlar Toplamı
static int rakamToplamı(int n) {
n = Math.abs(n);
if (n < 10) return n;
return n % 10 + rakamToplamı(n / 10);
}Örnekler
Palindrom Kontrolü
static boolean palindrom(String s, int sol, int sağ) {
if (sol >= sağ) return true;
if (s.charAt(sol) != s.charAt(sağ)) return false;
return palindrom(s, sol + 1, sağ - 1);
}- Her çağrı iki uçtan birer karakter çıkarır.
- Ortada sıfır veya bir karakter kaldığında sonuç true'dur.
Örnekler
Öklid ile EBOB
static int ebob(int a, int b) {
if (b == 0) return Math.abs(a);
return ebob(b, a % b);
}- Kalanlar küçülerek 0'a ulaşır.
- Son sıfır olmayan kalan EBOB'dur.
Çağrı Yığını
Çağrı Yığını
- Yeni çağrı yapıldığında mevcut metodun dönüş noktası saklanır.
- Temel durumdan sonra çağrılar ters sırada tamamlanır.
- Çok derin özyineleme StackOverflowError oluşturabilir.
Verimlilik
Özyineleme mi Döngü mü?
- Doğal olarak kendine benzeyen ağaç ve böl-parçala problemlerinde özyineleme açık olabilir.
- Basit doğrusal tekrarlar döngüyle daha az yığın belleği kullanır.
- Seçim yalnızca kod kısalığına değil doğruluk, okunabilirlik ve kaynak kullanımına dayanmalıdır.
Verimlilik
Faktöriyel Karşılaştırması
| Özellik | Özyinelemeli | Döngülü |
|---|---|---|
| Zaman | O(n) | O(n) |
| Ek yığın | O(n) | O(1) |
| Akış | Tanıma yakın | Açık sayaç |
| Derinlik riski | Var | Yok |
Verimlilik
Fibonacci Sorunu
- Doğrudan özyinelemeli tanım aynı alt sonuçları tekrar tekrar hesaplar.
- fibonacci(n-1) ve fibonacci(n-2) çağrı ağaçları büyük ölçüde örtüşür.
- Bu yaklaşımın çalışma süresi yaklaşık üstel büyür.
Verimlilik
Doğrudan Fibonacci
static long fib(int n) {
if (n <= 1) return n;
return fib(n - 1) + fib(n - 2);
}- Tanımı doğrudan yansıtır fakat büyük n için verimsizdir.
İyileştirme
Memoization
- Hesaplanan alt problem sonuçlarını önbellekte saklar.
- Aynı girdi tekrar geldiğinde yeni çağrı ağacı yerine kayıtlı değer döner.
- Zaman kazanımı karşılığında ek bellek kullanılır.
İyileştirme
Belleklemeli Fibonacci
static long fib(int n, long[] bellek) {
if (n <= 1) return n;
if (bellek[n] != 0) return bellek[n];
bellek[n] = fib(n-1, bellek) + fib(n-2, bellek);
return bellek[n];
}- Toplam zaman O(n), ek alan O(n) olur.
İyileştirme
Kuyruk Özyinelemesi
- Özyinelemeli çağrı metodun son işlemidir.
- Bazı diller kuyruk çağrılarını yığın büyütmeden optimize eder.
- Java dili/JVM genel olarak kuyruk çağrısı optimizasyonunu garanti etmez.
Doğrulama
Hata Ayıklama
- Temel durumun ulaşılabilir olduğunu kanıtlayın.
- Her çağrıda problemin hangi ölçüye göre küçüldüğünü yazın.
- Küçük girdi için çağrı ve dönüş sırasını tabloya dökün.
- Yığın derinliği ve tekrarlı alt problemleri değerlendirin.
Özet
Bölüm Özeti
- Özyineleme temel durum ve küçülen özyinelemeli adımdan oluşur.
- Çağrılar yığında birikir ve temel durumdan sonra ters sırada döner.
- Doğrusal tekrarlar çoğu zaman döngüyle daha az bellek kullanır.
- Memoization tekrarlanan alt problem sonuçlarını saklayarak zamanı azaltır.
Özet
Kontrol Soruları
- Temel durum olmazsa ne olur?
- Çağrı yığını neden ters sırada çözülür?
- Özyinelemeli faktöriyel ne kadar ek yığın kullanır?
- Doğrudan Fibonacci neden yavaştır?
- Java'da kuyruk özyinelemesi neden yığın güvenliği sağlamaz?
Son
Özyineleme
1 / 1Sercan KÜLCÜ, Tüm hakları saklıdır.
← → veya boşluk ile gezinin · F: tam ekran · Home/End: ilk/son slayt