Yrd. Doç. Dr. A. Burak İER Bilgisayar Mühendisliği
Algoritma Analizi İçerik: Temel Kavramlar Yinelemeli ve Yinelemesiz Algoritma Analizi Asimptotik otasyonlar
Temel Kavramlar Algoritma: Bir problemin çözümüne yönelik işlem basamaklarının sıralı olarak ifade edilmesidir. Program: Probleme ilişkin çözümlerin, herhangi bir programlama dili kullanarak, bilgisayarın anlayacağı komutlar dizisi şeklinde yazılmasına program, bilgisayarda kullanılan programların genel adına da yazılım denir. 3
Algoritma Analizi Algoritma, sistem kaynaklarının (çalışma süresi, bellek tüketimi vb.) önemli olduğu durumlarda etkili bir şekilde geliştirilmelidir. Bir problemin çözümünde kullanılabilecek algoritmalardan en etkin olanı seçilmelidir. eden Algoritmayı Analiz Ederiz? Algoritmanın performansını ölçmek için Daha iyisi mümkün mü? Farklı algoritmalarla karşılaştırmak için 4
Algoritma Analizi Zaman Karmaşıklığı: Problemi çözmek için algoritmanın harcadığı zamanın analizi Belirli bir giriş verisine karşılık yapılan karşılaştırma, atama, toplama, çıkarma vb. işlemlerin sayısı üzerinden hesaplanır. Yer karmaşıklığı: Gerekli belleğin analizi Kullanılan veri yapılarıyla ilgilidir. 5
Algoritmaların Analizi Bir algoritmanın çalışma süresini analiz etmek için o programın kaç adımda bittiğini (yürütme süresi) belirleriz. Özyinelemeli algoritmaların analizi farklı yapılır. Eğer analiz edilecek program (ya da fonksiyon) kendi kendini çağırıyorsa bu programa özyinelemeli program denir. 6
Örnek I: Dizideki sayıların toplamını bulma int Topla(int A[], int ) { int toplam = 0; Bu fonksiyonun yürütme zamanı ne kadardır? for (i=0; i < ; i++){ toplam += A[i]; } //Bitti-for return toplam; } //Bitti-Topla 7
Örnek I: Dizideki sayıların toplamını bulma İşlem int Topla(int A[], int ) { int topla = 0; sayısı 1 for (i=0; i < ; i++){ topla += A[i]; } //Bitti-for return topla; } //Bitti-Topla 1 -------- Toplam: 1 + + + 1 = + Çalışma zamanı: T() = + = O() dizideki eleman sayısı Giriş verisi 8
Örnek II: Dizideki bir elemanın aranması int Arama(int A[], int, int sayi) { int i = 0; while (i < ){ if (A[i] == sayi) break; i++; } //bitti-while if (i < ) return i; else return -1; } //bitti-arama İşlem sayısı 1 1 1 --------- Toplam: 1+3*+1+1 = 3+3 O() 9
Örnek II: Dizideki bir elemanın aranması En iyi çalışma zamanı nedir? Döngü sadece bir kez çalıştı=>t(n) = 6 Ortalama(beklenen) çalışma zamanı nedir? Döngü / kez çalıştı =>T(n)=3*n/+3 = 1.5n+3 En kötü çalışma zamanı nedir? Döngü kez çalıştı =>T(n) = 3n+3 10
Algoritmaların en kötü durum analizi Bir algoritmanın sadece E KÖTÜ durumdaki çalışma zamanına bakılır. eden? En kötü durum çalışma zamanında bir üst sınırdır ve o algoritma için verilen durumdan daha uzun sürmeyeceği garantisi verir. Bazı algoritmalar için en kötü durum oldukça sık rastlanır. Arama algoritmasında, aranan öğe genellikle dizide olmaz dolayısıyla döngü kez çalışır. Ortalama çalışma zamanı genellikle en kötü çalışma zamanı kadardır. Arama algoritması için hem ortalama hem de en kötü çalışma zamanı doğrusal fonksiyondur. 11
Yürütme Zamanından Big O Hesabı T ( ) An Bn C Algoritmanın karmaşıklığı T() yukarıdaki gibi hesaplanmış olsun. Bu algoritmanın Big-O notasyonuna göre karmaşıklığını hesaplayınız? An n Bn n C n 1
Yürütme Zamanından Big O Hesabı T ( ) An Bn C Çözüm: Eşitliğin sağ tarafı n ye bölünür. An n Bn n C n Burada n giderken ikinci ve üçüncü terim sıfıra yaklaşır. İlk terim yani A sabit olarak kalır. A B n C n Öyleyse karmaşıklık: O( ) 13
Örnek III: İç içe döngüler for (i=1; i<=; i++){ for (j=1; j<=; j++){ printf( Foo\n ); } //bitti-içteki for } //bitti-dıştaki for Prinf fonksiyonu kaç kez çalıştırıldı? Veya Foo yazısı ekrana kaç kez yazılır? T( ) 1 * i1 j1 i1 14
Örnek IV: İç içe döngüler T() nedir? toplam = 0; for(int i =1; i<=; i++) toplam += i*i; for(int k =1; k<=; k++) for(int j =1; j<=; j++) toplam++; T( ) 1 1 * i1 k1 j1 15
Örnek V: Matris Çarpımı /* İki boyutlu dizi A, B, C. Hesapla C = A*B */ for (i=0; i<; i++) { for (j=0; j<; j++) { C[i][j] = 0; for (int k=0; k<; k++){ C[i][j] += A[i][k]*B[k][j]; } //bitti-en içteki for } //bitti-içteki for } //bitti-dıştaki for T( ) 1 1 (1 1 1) 3 i0 j0 k0 16
Örnek VI: İkili Arama Problem: Sıralı bir dizi veriliyor ve bir sayıyı arıyorsunuz. Doğrusal arama T(n) = 3n+ (En kötü durum) Daha iyisi yapılabilir mi? Ö.g. Aşağıdaki sıralı dizide 55 sayısını arayalım 0 1 3 4 5 6 7 8 9 10 11 1 13 14 15 3 8 10 11 0 50 55 60 65 70 7 90 91 94 96 99 17
Örnek VI: İkili Arama Dizi sıralanmış olduğundan, dizinin ortasında bulunan sayı ile aranan sayıyı karşılaştırarak arama boyutunu yarıya düşürülür ve bu şekilde devam edilir. Örnek: 55 i arayalım 0 1 3 4 7 8 11 3 8 10 11 0 50 55 60 65 70 7 90 15 91 94 96 99 sol orta ( sol sağ) sağ 0 1 3 4 6 7 8 11 3 8 10 11 0 50 55 60 65 70 7 90 15 91 94 96 99 sol orta sağ Elendi 18
İkili arama (devam) 0 1 3 4 5 6 7 8 11 3 8 10 11 0 50 55 60 65 70 7 90 15 91 94 96 99 Elendi sol orta 0 1 3 4 5 6 7 8 11 3 8 10 11 0 50 55 60 65 70 7 90 15 91 94 96 99 Elendi orta 55 i bulduk Başarılı arama 57 yi aradığımızda, bir sonraki işlemde başarısız bir şekilde sonlanacak. 19
İkili Arama (devam) < hedef? > hedef sol sağ Hedefi ararken herhangi bir aşamada, arama alanımızı sağ ile sol arasındaki alana kısıtlamış oluyoruz. sol un solunda kalan alan hedeften küçüktür ve bu alan arama alanından çıkarılır. sağ ın sagında kalan alan hedeften büyüktür ve bu alan arama alanından çıkarılır. 0
İkili Arama - Algoritma // Aranan sayının indeksini döndürür aranan sayı bulunamazsa -1 döndürür. int ikiliarama(int A[], int, int sayi){ sol = 0; sag = -1; while (sol <= sag){ int orta = (sol+sag)/; // Test edilecek sayının indeksi if (A[orta] == sayi) return orta; // Aranan sayı bulundu. İndeksi döndür else if (sayi < A[orta]) sag = orta 1; // Sağ tarafı ele else sol = orta+1; // Sol tarafı ele } //bitti-while return 1; // Aranan sayı bulunamadı } //bitti-ikiliarama En kötü çalışma zamanı: T(n) = 3 + 5*log. eden? 1
Örnek VII: Logaritma int basamak_sayisi(int ){ int i, sayi = 1; while( > 1){ sayi++; = / ; } } O(log) 1 k k log k
Çalışma zamanı Asimptotik otasyon Bir problemi çözmek için A ve B şeklinde iki algoritma verildiğini düşünelim. Giriş boyutu için aşağıda A ve B algoritmalarının çalışma zamanı T A ve T B fonksiyonları verilmiştir. Hangi algoritmayı seçersiniz? Giriş Boyutu () 3
Running Time Asimptotik otasyon (devam) büyüdüğü zaman A ve B nin çalışma zamanı: Şimdi hangi algoritmayı seçersiniz? Giriş Boyutu () 4
Asimptotik otasyon (devam) Genel olarak, asimptotik notasyon, eleman sayısı n nin sonsuza gitmesi durumunda algoritmanın, benzer işi yapan algoritmalarla karşılaştırmak için kullanılır. Eleman sayısının küçük olduğu durumlar pratikte mümkün olabilir fakat bu birçok uygulama için geçerli değildir. Verilen iki algoritmanın çalışma zamanını T1() ve T() fonksiyonları şeklinde gösteriyoruz. Fakat hangisinin daha iyi olduğunu belirlemek için bir yol belirlememiz gerekiyor. (asimptotik olarak daha küçük gibi) Asimptotik notasyonlar Büyük-O, W, Q notasyonları 5
Karşılaşılan Genel Fonksiyonlar İsim Büyük-O Yorum Sabit O(1) Yenilmez! Logaritmik O(log) İyi hazırlanmış arama algoritmalarının tipik zamanı Doğrusal O() Hızlı bir algoritmadır. tane veriyi girmek için gereken zaman. log O(log) Çoğu sıralama algoritması Karesel O( ) Veri miktarı az olduğu zamanlarda uygun (<1000) Kübik O( 3 ) Veri miktarı az olduğu zamanlarda uygun (<1000) Üssel O( ) Veri miktarı çok az olduğunda uygun (n<=0) 6
Örnekler Büyük-O O(1) O(log) O() O(log) O( ) O( 3 ) Yorum elemanlı bir dizinin i. Elemanına bir değer atanması Sıralı bir listenin elemanları içinde ikili arama elemanlı bir dizinin tüm elemanlarının ekrana yazdırılması Bazı hızlı sıralama algoritmaları (merge sort) gibi Basit sıralama algoritmaları (selection sort gibi) Üç boyutlu bir tamsayı tablosundaki her elemanın değerini artıran algoritma 7
Karşılaşılan Genel Fonksiyonlar (devam) 8
Tanım: Verilen bir tamsayı listesi içerisinde/dizisinde elemanları komşu olmak şartıyla hangi (bitişik) alt dizi en yüksek toplamı verir? Örneğin: Örnek: Maksimum Alt Dizi Toplamı { -,11,-4,13,-5, } Cevap=0 { 1,,-5,4,7,- } Cevap=11 { 1,5,-3,4,-,1 } Cevap=7 Bu problemi çözen çok sayıda algoritma vardır. 9
Çözüm-1 Kaba Kuvvet Algoritması public static int maxaltdizit( int[] a){ } int maxtop = 0; for(int i=0; i<a.length; i++) for(int j=i; j<a.length; j++){ } int top=0; for(int k=i; k<=j; k++) top += a[k]; if(top > maxtop){ } return maxtop; maxtop = top; int bas = i; int son = j; // alt dizinin başlangıcı // alt dizinin sonu Bu algoritmanın karmaşıklığı nedir? n 3 +6n +n+ O(n 3 ) Daha iyisi yapılabilir mi? 30
Çözüm- Geliştirilmiş Algoritma public static int maxaltdizit(int[] a) { } int maxtop = 0; for (int i = 0; i < a.length; i++) { } int top = 0; for (int j = i; j <= a.length; j++) { } top += a[j]; if (top > maxtop) { } return maxtop; maxtop = top; int bas = i; int son = j; // alt dizinin başlangıcı // alt dizinin sonu Bu algoritmanın karmaşıklığı nedir? 6n +n+ O(n ) Daha iyisi yapılabilir mi? 31
Çözüm-3 Doğrusal Algoritma public static int maxaltdizit(int[] a) { int maxtop = 0; int top = 0; for (int i=0, j=0; j<=a.length; j++) { } top += a[j]; if (top > maxtop) { maxtop = top; int bas = i; int son = j; } else if (top<0){ } i = j + 1; top = 0; return maxtop; // alt dizinin başlangıcı // alt dizinin sonu 9n+3 O(n) Bu algoritmanın karmaşıklığı nedir? Daha iyisi yapılabilir mi? } 3
Maksimum Alt Dizi Toplamı Çalışma Süresi Çeşitli Maksimum Alt Dizi Toplamı algoritmaları için çalışma süreleri aşağıda verilmiştir. (saniye cinsinden) O( 3 ) O( ) O( log ) O() 10 0,000001 0,000000 0,000001 0,000000 100 0,00088 0,000019 0,000014 0,000005 1 000 0,3111 0,001630 0,000154 0,000053 10 000 18 0,133064 0,001630 0,000533 100 000 A 13,17 0,017467 0,005571 1 000 000 A A 0,185363 0,056338 33
Özyinelemeli Algoritmaların Analizi Özyinelemeli algoritmaların analizinin farklı yapılmasının nedeni: programın çalışma süresinin sadece yapılan işlemlerle değil aynı zamanda programın kendi çalışma süresinin bir fonksiyonuna bağlı olmasıdır. int faktoriyel(int ){ if( <= 1) return 1; else return * faktoriyel(-1); } 34
Özyinelemeli Algoritma Örnek - I int faktoriyel(int ){ if( <= 1) return 1; else return * faktoriyel(-1); } girdisi için çalışma süresi yine faktöriyel 1 girdisi için çalışma süresine bağlıdır. Matematiksel olarak: f (1) 1 f ( ) f ( 1) 1 Eşitliğin sağ tarafı işlem miktarını göstermektedir. 35
Özyinelemeli Algoritma Örnek - I Faktöriyel fonksiyonun çalışma zamanını bulabilmek için özyinelemeli denklem sistemini çözmemiz gerekir. f() = f( 1) + 1 f(-1) = f( ) + 1 f(-) = f( 3) + 1 f() = f(1) + 1 Eşitlikleri taraf tarafa toplarsak, f(-1), f(-),, f() sadeleşir ve geriye kalan ifade: f() = f(1) + 1 f() = O() 36
Özyinelemeli Algoritma Örnek - II int basamak_sayisi(int ){ if( == 1) return 1; else return 1 + basamak_sayisi( / ); } Bu fonksiyonun çalışma süresi (girdi ) yine bu fonksiyonun (girdi /) çalışma süresine bağlıdır. b(1) 1 b( ) b( / ) 1 Eşitliğin sağ tarafı yapılacak işlemin adedidir. 37
Özyinelemeli Algoritma Örnek - II 38 1 ) (... 1 ) ( ) ( 1 ) ( ) ( 1 ) ( ) ( 1 1 3 1 1 b b b b b b b b k k k k k k İfadeler taraf tarafa toplanır.
Özyinelemeli Algoritma Örnek - II Devamı b( k ) b(1) k b( k ) k 1 b( ) log 1O(log ) 39
Big O otasyonu Zaman Karmaşıklığı Paul Bechman tarafından tanıtılmıştır. Zaman karmaşıklığında üst sınırı gösterir. Bu notasyon bir çok ifadeyi sadeleştirmemizi sağlar. Big Omega otasyonu W Big O notasyonunun tam tersidir. Zaman karmaşıklığında alt sınırı gösterir. Omega ile ölçülen değerden daha hızlı bir değer elde edilemez. Big Theta otasyonu Q Bu notasyon Big O notasyonu ile Big Omega notasyonu arasında ortalama bir karmaşıklığı ifade eder. 40
Sıkça Yapılan Hatalar Karmaşıklığı bulmak için sadece döngüleri saymakla yetinmeyin. içi içe döngünün 1 den kadar döndüğünü düşünürsek karmaşıklık O( 4 ) olur. O( ) veya O( +) gibi ifadeler kullanmayın. Sadece baskın terim kullanılır. Öndeki sabitler kaldırılır. İç içe döngüler karmaşıklığı direk etkilerken art arda gelen döngüler karmaşıklığı etkilemez. 41
Dersin Sonu