Sıralama Algoritmaları

advertisement
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;
}
Download