Sıralama Algoritmaları • Bilgisayar bilimlerinde yada matematikte kullanılan, verilen bir listenin elemanlarını belirli bir sıraya sokan algoritmalardır. • Sıralama algoritmaları, tanımı çok yalın olmasına karşın çözümü çok karmaşık olan bir işi gerçekleştirdikleri için, üzerinde en fazla araştırma yapılan bilgisayar bilimi konularından biridir. • Hesaplama karmaşıklığı: Dizideki öğelerin karşılaştırılmasının en iyi, ortalama ve en kötü başarımının dizinin boyutu (n) cinsinden gösterilmiş halidir. • Olağan uygulamalarda sıralama algoritmalarının iyi durum başarımı O(n log n) ve kötü durum başarımı ise Ω(n²)'dir. • Bir sıralama algoritmasının istenen karmaşıklığı O(n)'dir. Yalnızca soyut bir anahtar karşılaştırması yapan bütün sıralama algoritmaları en kötü durumda her zaman Ω(n log n) karşılaştırma yaparlar. • Bellek (ve diğer donanım kaynaklarının) Kullanımı: Bazı sıralama algoritmaları dizinin içerdiği öğelerin dizinin saklandığı alanda sıralar. • Böylece sıralanan öğeler dışında yalnızca O(1) ya da O(log n)'lik bir ek bellek alanı gerekir. Bazı algoritmalar ise verinin geçici olarak saklanması için dizinin tutulduğu alanın dışında ek bellek alanlarına gereksinim duyar. Kararlılık • Kararlı sıralama algoritmaları sıralanacak dizinin içinde değerleri birbirine eşit olan öğelerin birbirlerine göre olan konumlarını korur. • Bir sıralama algoritması kararlı olduğunda, eğer R ve S gibi içerdiği değer aynı olan iki öğe bulunduran asıl dizide, R S' den önce geliyorsa, sıralanmış dizide de R, S'den önce gelir. Sıralama Algoritmaları Listesi Adı Ortalama Kabarcık Sıralaması En Kötü Bellek Kararlı mı Yöntem O(n2) O(1) Evet Değiştirme Eklemeli O(n+d) O(n2) O(1) Evet Ekleme Seçmeli O(n2) O(n2) O(1) Hayır Seçme O(log2n) O(1) Hayır Ekleme O(n2) O(log n) Hayır Bölümlendirme Kabuk Sıralama Hızlı Sıralama O(n log n) Kabarcık Sıralaması • Sıralanacak dizinin üzerinde sürekli ilerlerken her defasında iki öğenin birbiriyle karşılaştırılıp, karşılaştırılan öğelerin yanlış sırada olmaları durumunda yerlerinin değiştirilmesi mantığına dayanır. • Algoritma, herhangi bir değişiklik yapılmayıncaya kadar dizinin başına dönerek kendisini yineler. • Adına "Kabarcık" sıralaması denmesinin nedeni büyük olan sayıların aynı suyun altındaki bir kabarcık gibi dizinin üstüne doğru ilerlemesidir. Kabarcık Sıralaması • Kabarcık sıralaması dizinin başından başlar ve dizi elemanlarını sırayla seçer. • Seçilen dizi elemanı kendinden sonra gelen elemandan büyükse bu iki elemanın yerleri değiştirilir. • Bu işlem sonucunda dizinin en büyük elemanı dizi sonuna yerleştirildiğinden bir sonraki adımda arama sınırı bir eleman geri çekilir. • Bu işlem, dizinin sonundaki elemanın karşılaştırılmasına kadar yinelenerek sürdürülür. • İçeriği "5 1 4 2 8" olan bir dizi kabarcık sıralaması ile en küçükten en büyüğe doğru aşağıdaki biçimde sıralanır. • Birinci Geçiş: ( 5 1 4 2 8 ) ( 1 5 4 2 8 ) Burada algoritma ilk iki elemanı karşılaştırır ve yerlerini değiştirir. (15428) (14528) (14528) (14258) ( 1 4 2 5 8 ) ( 1 4 2 5 8 ) Burada elemanlar zaten sıralı olduğu için algoritma yerlerini değiştirmez. Kabarcık Sıralama • İkinci Geçiş: (14258) (14258) (14258) (12458) (12458) (12458) (12458) (12458) • Artık dizi sıralıdır ancak algoritma işlemin bittiğini bilmemektedir. Algoritmanın dizinin sıralandığını anlaması için bütün dizinin üzerinden hiçbir değişiklik yapmadan tam bir geçiş yapması gerekir. • Üçüncü Geçiş: (12458) (12458) (12458) (12458) (12458) (12458) (12458) (12458) Sonuç olarak dizi sıralanmıştır ve algoritma sonlanır. • http://www.youtube.com/watch?v=lyZQPjUT5B4 Kabarcık Sıralama • Analizi kolaydır (İyileştirme yapılmamış algoritmada) : • (n-1) iterasyon ve her iterasyonda (n-1) karşılaştırma. • Toplam karşılaştırma sayısı : (n-1)*(n-1) = n2-2n+1 = O(n2) Kabarcık Sıralama • • • • • • • • • • • • • • • • private static int[] KabarcikSiralama(int[] dizi) { for (int i = 0; i < dizi.Length - 1; i++) { for (int j = 1; j < dizi.Length - i; j++) { if (dizi[j] < dizi[j - 1]) { int temp = dizi[j - 1]; dizi[j - 1] = dizi[j]; dizi[j] = temp; } } } return dizi; } Eklemeli Sıralama (Insertion Sort) • Uygulaması kolaydır. • Küçük Veri kümeleri üzerinde kullanıldığında verimlidir. • Çoğunluğu zaten sıralanmış olan diziler üzerinde kullanıldığında verimlidir. • Karmaşıklığı olan seçmeli sıralama ve kabarcık sıralaması gibi çoğu yalın sıralama algoritmalarından daha verimlidir. • Kararlı bir sıralama algoritmasıdır (değeri eşit olan öğelerin asıl listedeki göreceli konumlarını değiştirmez) • Sıralanacak diziyi yerinde sıralar, ek bir bellek alanı gerektirmez. • Sıralanacak dizinin hepsinin algoritmanın girdisi olmasına gerek yoktur. Dizi parça parça da alınabilir ve sıralama işlemi sırasında diziye yeni veriler eklenebilir. Eklemeli Sıralama • Eleman kümesinin (array/dizi) 2. elemanından başlayarak kendinden önceki elemanlarla karşılaştırma yapar. • Karşılaştırma yaptığı elemanlar kendinden büyükse bu elemanlar, küme içerisinde sağa doğru kaydırılır. Ve seçili eleman uygun yere yerleştirilir. • http://www.youtube.com/watch?v=ROalU379 l3U Eklemeli Sıralama • • • • • • • • • • • • • • • • • • public static int[] eklemeliSiralama(int[] dizi) { int gecici, eklenen; for (int i = 1; i < dizi.Length; i++) { eklenen = dizi[i]; //dizinin ilk elemanını al gecici = i; //indeks değerini gecici değişkeninde sakla while (gecici > 0 && dizi[gecici - 1] > eklenen) { //Eğer adım sayısı >0 ve dizinin n-1. elemanın değeri eklenen //Eklenen değerden büyükse dizi[gecici] = dizi[gecici - 1]; //n-1. elemanı sona kaydır gecici--; //indeks değerini 1 azalt.. } dizi[gecici] = eklenen; //Yeri değiştirilen elemanı diziye geçir.. } return dizi; }//** Seçmeli Sıralama (Selection Sort) • Büyük listeler üzerinde kullanıldığında verim sağlamaz ve genel olarak benzeri olan eklemeli sıralamadan daha başarısızdır. • Seçmeli sıralama yalın olduğu ve bazı durumlarda daha karmaşık olan algoritmalardan daha iyi sonuç verdiği için tercih edilebilir. Seçmeli Sıralama • Algoritma aşağıdaki gibi çalışır: 1. Listedeki en küçük değerli öğeyi bul. 2. İlk konumdaki öğeyle bulunan en küçük değerli öğenin yerini değiştir. 3. Yukarıdaki adımları listenin ilk elemanından sonrası için (ikinci elemandan başlayarak) yinele. http://www.youtube.com/watch?v=Ns4TPTC8whw • • • • • • • • • private static int[] SecmeliSiralama(int[] dizi) { int i, j; int enKucukDeger; int enKucukIndex; for (i = 0; i < dizi.Length; i++) { enKucukDeger = dizi[i]; enKucukIndex = i; • • • • • • • • for (j = i + 1; j < dizi.Length; j++) { if (dizi[j] < enKucukDeger) { enKucukDeger = dizi[j]; enKucukIndex = j; } } • • • • dizi[enKucukIndex] = dizi[i]; dizi[i] = enKucukDeger; } return dizi; Kabuk Sıralama (Shell Sort) • Kabuk sıralama algoritması dizi elemanlarını dizinin uzunluğuna göre belirlenen atlama payına göre karşılaştırır. • Mesela 0. eleman ile 3. elemanı karşılaştırır. 0. eleman büyükse yer değiştirirler. Ta ki atlama payi 1'den küçük kalana kadar. • Atlama payını da dizi büyüklüğüne göre biz belirliyoruz. Mesela n elemanlı dizimiz olsun. n/2 bizim dizideki atlama payımızdır. 7 elemanlı ise 7 / 2 = 3.5 = 3'er 3'er atlatacağız her döngüden sonra n /= 2 ile yeni atlama miktarı belirliyoruz. 3 / 2 = 1.5 = 1...Bu adımdan sonra elemanlar arasında birer birer atlama yapar. Kabuk Sıralama http://www.youtube.com/watch?v=CmPA7zE8mx0 Kabuk Sıralama • • private static int[] KabukSiralama(int[] dizi) { • • • int j; int temp; int orta = dizi.Length / 2; • • • • • • • • • • • • • • • • • • // Kabuk sıralama, while (orta > 0) { for (int i = orta; i < dizi.Length; i++) { temp = dizi[i]; j = i; while (j >= orta && dizi[j - orta] > temp) { dizi[j] = dizi[j - orta]; j -= orta; } dizi[j] = temp; } orta = orta / 2; } return dizi; } Hızlı Sıralama (Quicksort) • Hızlı sıralama algoritması, sıralanacak bir sayı dizisini daha küçük iki parçaya ayırıp oluşan bu küçük parçaların kendi içinde sıralanması mantığıyla çalışır. Hızlı Sıralama • Algoritmanın adımları aşağıdaki gibidir: 1. Sayı dizisinden herhangi bir sayıyı pivot eleman olarak seç. 2. Sayı dizisini pivottan küçük olan tüm sayılar pivotun önüne, pivottan büyük olan tüm sayılar pivotun arkasına gelecek biçimde düzenle (pivota eşit olan sayılar her iki yana da geçebilir). Bu bölümlendirme işleminden sonra eleman sıralanmış son dizide olması gerektiği yere gelir. Algoritmanın bu aşamasına bölümlendirme aşaması denir. 3. Pivotun sol ve sağ yanında olmak üzere oluşan iki ayrı küçük sayı dizisi, hızlı sıralama algoritması bu küçük parçalar üzerinde yeniden özyineli olarak çağrılarak sıralanır. 4. Algoritma içinde sayı kalmayan (eleman sayısı sıfır olan) bir alt diziye ulaştığında bu dizinin sıralı olduğunu varsayar. 5. http://www.youtube.com/watch?v=ywWBy6J5gz8 • • • • • • • • • • public static int[] HizliSiralama(int[] dizi, int sol, int sag) • { • int i = sol, j = sag; • int pivot = dizi[(sol + sag) / 2]; • while (i <= j) { while (dizi[i].CompareTo(pivot) < 0) { i++; } • • • • while (dizi[j].CompareTo(pivot) > 0) { j--; } • • • • • • if (i <= j) { // Swap int tmp = dizi[i]; dizi[i] = dizi[j]; dizi[j] = tmp; i++; j--; } } • • • • • // Recursive calls if (sol < j) { HizliSiralama(dizi, sol, j); } • • • • if (i < sag) { HizliSiralama(dizi, i, sag); } • • return dizi; }