Bölüm 2: Sıralama Algoritmaları

Algoritmalar
Kararlılık ve yerinde sıralamaKabarcıkEklemeliSeçmeliKabuk BirleştirmeliHızlıYığınSaymalı ve basamakTimsortKarşılaştırma
Sercan KÜLCÜ · Giresun Üniversitesi · Bilgisayar Mühendisliği

Giriş

Öğrenme Çıktıları

Kavramlar

Sıralamayı; zaman, ek bellek, kararlılık, yerinde çalışma ve karşılaştırmalı / karşılaştırmasız olma ölçütleriyle değerlendirmek.

Basit algoritmalar

Kabarcık, eklemeli, seçmeli ve kabuk sıralamayı bir dizi üzerinde adım adım izlemek ve Java ile yazmak.

Böl ve fethet, yığın

Birleştirmeli, hızlı ve yığın sıralamanın çalışmasını açıklamak; O(n log n) ve en kötü durum davranışlarını gerekçelendirmek.

Doğrusal zaman ve seçim

Karşılaştırma alt sınırını, saymalı ve basamak sıralamayı açıklamak; bir problem için uygun algoritmayı seçmek.

Giriş

Sıralama Algoritmaları

  • Alışveriş listelerinden sosyal medya gönderilerine kadar dijital dünyada sürekli veri ile karşılaşırız.
  • Verinin etkin kullanılabilmesi için düzenli tutulması gerekir.
  • Sıralama algoritmaları (sorting algorithms) bir listedeki öğeleri belirli bir ölçüte göre düzenler:
    • sayısal değer,
    • alfabetik sıra,
    • tarih …
  • Sıra artan (küçükten büyüğe) ya da azalan olabilir.
Sırasız72941sırala (artan)Sıralı12479
Sıralı veride ikili arama O(log n), tekrar bulma, birleştirme, medyan ve en küçük/en büyük k eleman gibi işlemler çok kolaylaşır.

Giriş

Sıralama Algoritmalarının Çeşitleri

Farklı sıralama algoritmaları farklı çalışma prensiplerine sahiptir:

AlgoritmaTemel fikir
Kabarcık (Bubble Sort)Komşu elemanları karşılaştırır, yanlış sıradaysa yer değiştirir.
Eklemeli (Insertion Sort)Sıradaki elemanı sıralı kısımda doğru konuma yerleştirir.
Seçmeli (Selection Sort)En küçük elemanı bulup başa yerleştirir, sonra kalanları sıralar.
Kabuk (Shell Sort)Uzak elemanlarla başlayan, aralığı küçülen eklemeli sıralama.
Birleştirmeli (Merge Sort)Diziyi yarıya böler, sıralar, sonra birleştirir.
Hızlı (Quick Sort)Pivot etrafında parçalar, iki parçayı özyinelemeli sıralar.
Yığın (Heap Sort)Max-heap kurar, en büyüğü tekrar tekrar sona taşır.
Saymalı / Basamak (Counting / Radix)Karşılaştırma yapmaz; anahtarları sayar ya da basamak basamak dağıtır.
TimsortEklemeli + birleştirmeli karması; Java ve Python'un nesne sıralaması.

Giriş

Bir Sıralama Algoritmasını Değerlendirmek

ZamanEn iyi, ortalama ve en kötü durumda karşılaştırma ve yer değiştirme (taşıma) sayısı: Θ(n²), Θ(n log n), Θ(n + k) …
Ek bellekGirdinin dışında gereken alan. O(1) ek bellekle çalışan algoritma yerinde (in-place) sıralar.
KararlılıkEşit anahtarlı elemanların göreli sırası korunuyorsa algoritma kararlıdır (stable).
Karşılaştırmalı mı?Yalnızca "a ≤ b?" sorusuyla çalışan algoritmalar en az Ω(n log n) karşılaştırma yapar. Saymalı ve basamak sıralama bu sınırın dışındadır.
UyarlanabilirlikNeredeyse sıralı girdide daha hızlı çalışan algoritma uyarlanabilirdir (adaptive): eklemeli, bayraklı kabarcık, Timsort.
ÇevrimiçiVeri geldikçe sıralayabilen algoritma çevrimiçidir (online): eklemeli sıralama.

Giriş

Kararlılık (Stability): Örnek

Girdi(3, A)(1, B)(3, C)(2, D)(1, E)(3, F)3'ler: ACFKararlı (eklemeli)(1, B)(1, E)(2, D)(3, A)(3, C)(3, F)3'ler: ACFKararsız (seçmeli)(1, B)(1, E)(2, D)(3, C)(3, A)(3, F)3'ler: CAF

Kayıtlar yalnızca sayıya (anahtar) göre sıralanır; harf, kaydın kimliğidir. Kararlı algoritmada anahtarı 3 olanlar girdideki gibi A, C, F sırasında kalır; seçmeli sıralamanın uzun mesafeli takasları bu sırayı C, A, F yapar. (Bu girdi, simülatör laboratuvarındaki örnektir.)

Kararlılık, çok anahtarlı sıralamada önemlidir: öğrencileri önce ada, sonra (kararlı bir algoritmayla) bölüme göre sıralarsanız her bölümün içi alfabetik kalır. Basamak sıralama da bu yüzden kararlı bir ara adım ister.

Kabarcık Sıralama

Kabarcık Sıralama (Bubble Sort)

  • Her turda dizideki büyük elemanlar dizinin sonuna doğru kaydırılır; su içindeki kabarcık gibi yükselir.
  • Komşu elemanlar ikili olarak karşılaştırılır.
  • Sol eleman büyükse yerleri değiştirilir (swap).
  • i. tur bittiğinde en büyük i eleman son yerlerindedir; bir sonraki tur bir eleman kısa olur.
  • Bir turda hiç yer değiştirme olmazsa dizi sıralıdır → erken çıkış.
1. tur öncesi: komşu çiftler3152641. tur sonrası132546en büyük sonda

Kabarcık Sıralama · Adım adım

Kabarcık Sıralama Adım Adım: [3, 1, 5, 2, 6, 4]

Başlangıç301152236445

Dizi: [3, 1, 5, 2, 6, 4]. Her turda komşu çiftler soldan sağa karşılaştırılır; büyük olan sağa kayar.

1. Turjj+1301152236445

1. tur, j = 0: 3 > 1? Evet → yer değiştirilecek.

1. Turjj+1103152236445takas

Yer değiştirme (takas): dizi artık [1, 3, 5, 2, 6, 4].

1. Turjj+1103152236445

1. tur, j = 1: 3 > 5? Hayır → yerinde kalır.

1. Turjj+1103152236445

1. tur, j = 2: 5 > 2? Evet → yer değiştirilecek.

1. Turjj+1103122536445takas

Yer değiştirme (takas): dizi artık [1, 3, 2, 5, 6, 4].

1. Turjj+1103122536445

1. tur, j = 3: 5 > 6? Hayır → yerinde kalır.

1. Turjj+1103122536445

1. tur, j = 4: 6 > 4? Evet → yer değiştirilecek.

1. Turjj+1103122534465takas

Yer değiştirme (takas): dizi artık [1, 3, 2, 5, 4, 6].

1. Tur sonu103122534465

1. tur bitti: en büyük kalan eleman 6 son yerine (indis 5) yerleşti.

2. Turjj+1103122534465

2. tur, j = 0: 1 > 3? Hayır → yerinde kalır.

2. Turjj+1103122534465

2. tur, j = 1: 3 > 2? Evet → yer değiştirilecek.

2. Turjj+1102132534465takas

Yer değiştirme (takas): dizi artık [1, 2, 3, 5, 4, 6].

2. Turjj+1102132534465

2. tur, j = 2: 3 > 5? Hayır → yerinde kalır.

2. Turjj+1102132534465

2. tur, j = 3: 5 > 4? Evet → yer değiştirilecek.

2. Turjj+1102132435465takas

Yer değiştirme (takas): dizi artık [1, 2, 3, 4, 5, 6].

2. Tur sonu102132435465

2. tur bitti: en büyük kalan eleman 5 son yerine (indis 4) yerleşti.

3. Turjj+1102132435465

3. tur, j = 0: 1 > 2? Hayır → yerinde kalır.

3. Turjj+1102132435465

3. tur, j = 1: 2 > 3? Hayır → yerinde kalır.

3. Turjj+1102132435465

3. tur, j = 2: 3 > 4? Hayır → yerinde kalır.

3. Tur sonu102132435465

3. turda hiç yer değiştirme olmadı → dizi sıralı; algoritma erken durur. Sonuç: [1, 2, 3, 4, 5, 6].

Kabarcık Sıralama

Kabarcık Sıralama: Java Kodu

boolean yerDegistiMi;
for(int i = 0; i < n - 1; i++) {
  yerDegistiMi = false;
  for(int j = 0; j < n - 1 - i; j++) {
    if(dizi[j] > dizi[j+1]) {
      int gecici = dizi[j];
      dizi[j] = dizi[j+1];
      dizi[j+1] = gecici;
      yerDegistiMi = true;
    }
  }
  if(yerDegistiMi == false) break;
}
  • Dış döngü (i): en fazla n − 1 tur.
  • İç döngü (j): sıralanmamış kısımdaki komşu çiftler; sondaki i eleman zaten yerinde olduğu için j < n − 1 − i.
  • Yer değiştirme gecici değişkeniyle üç atamada yapılır.
  • yerDegistiMi bayrağı: tur boyunca hiç değiştirme yoksa dizi sıralıdır → break.
Koşul > olduğu (≥ değil) için eşit elemanlar asla yer değiştirmez: kabarcık sıralama kararlıdır.

Kabarcık Sıralama · Kodu adım adım çalıştır

Kabarcık Sıralama: Kodu İzle, dizi = [5, 1, 9, 2, 10]

dizi[]50119223104

n = 5. yerDegistiMi bayrağı tanımlanır.

dizi[]50119223104

Dış döngü i = 0: bayrak false yapılır.

dizi[]jj+150119223104

j = 0: dizi[0] = 5 > dizi[1] = 1? Evet.

dizi[]jj+110519223104yer değiştir

gecici = 5 ile yer değiştirilir; bayrak true.

dizi[]jj+110519223104

j = 1: dizi[1] = 5 > dizi[2] = 9? Hayır.

dizi[]jj+110519223104

j = 2: dizi[2] = 9 > dizi[3] = 2? Evet.

dizi[]jj+110512293104yer değiştir

gecici = 9 ile yer değiştirilir; bayrak true.

dizi[]jj+110512293104

j = 3: dizi[3] = 9 > dizi[4] = 10? Hayır.

dizi[]10512293104

Tur sonu: 10 yerine oturdu. Bayrak true → devam.

dizi[]10512293104

Dış döngü i = 1: bayrak false yapılır.

dizi[]jj+110512293104

j = 0: dizi[0] = 1 > dizi[1] = 5? Hayır.

dizi[]jj+110512293104

j = 1: dizi[1] = 5 > dizi[2] = 2? Evet.

dizi[]jj+110215293104yer değiştir

gecici = 5 ile yer değiştirilir; bayrak true.

dizi[]jj+110215293104

j = 2: dizi[2] = 5 > dizi[3] = 9? Hayır.

dizi[]10215293104

Tur sonu: 9 yerine oturdu. Bayrak true → devam.

dizi[]10215293104

Dış döngü i = 2: bayrak false yapılır.

dizi[]jj+110215293104

j = 0: dizi[0] = 1 > dizi[1] = 2? Hayır.

dizi[]jj+110215293104

j = 1: dizi[1] = 2 > dizi[2] = 5? Hayır.

dizi[]10215293104

Bu turda yer değiştirme yok: break. Dizi sıralı: [1, 2, 5, 9, 10].

boolean yerDegistiMi;
for(int i = 0; i < n - 1; i++) {
  yerDegistiMi = false;
  for(int j = 0; j < n - 1 - i; j++) {
    if(dizi[j] > dizi[j+1]) {
      int gecici = dizi[j];
      dizi[j] = dizi[j+1];
      dizi[j+1] = gecici;
      yerDegistiMi = true;
    }
  }
  if(yerDegistiMi == false) break;
}

Kabarcık Sıralama

Kabarcık Sıralama: Analiz

DurumGirdiKarşılaştırmaYer değiştirmeZaman
En iyisıralın − 1 (tek tur, bayrakla)0Θ(n)
Ortalamarastgele≈ n²/2≈ n²/4Θ(n²)
En kötüters sıralın(n − 1)/2n(n − 1)/2Θ(n²)
Artıları
  • Anlaşılması ve yazılması çok kolay.
  • Yerinde (O(1) ek bellek) ve kararlı.
  • Bayrakla sıralı girdiyi Θ(n)'de tanır.
Eksileri
  • Θ(n²): büyük dizilerde çok yavaş.
  • Çok fazla yer değiştirme yapar (her ters çift = 1 takas).
  • Pratikte eklemeli sıralamadan hep yavaştır.

Ters çift (inversion): i < j iken dizi[i] > dizi[j]. Kabarcık ve eklemeli sıralama her adımda tam olarak bir ters çifti düzeltir; ters sıralı dizide n(n − 1)/2 ters çift vardır.

Eklemeli Sıralama

Eklemeli Sıralama (Insertion Sort)

  • Eldeki oyun kartlarını sıralamaya benzer: her yeni kartı elinizdeki sıralı kartların arasına yerleştirirsiniz.
  • Dizi iki parçaya ayrılır: sıralı kısım (solda) ve sırasız kısım.
  • Sırasız kısmın ilk elemanı alınır, sıralı kısımda doğru konumuna yerleştirilir.
  • Bunun için ondan büyük elemanların bir sağa kaydırılması gerekir.
sıradaki103152236445← sıralısırasız →

Eklemeli Sıralama · Adım adım

Eklemeli Sıralama Adım Adım: [3, 1, 5, 2, 6, 4]

Başlangıç301152236445← sıralısırasız →

Dizi [3, 1, 5, 2, 6, 4]. İlk eleman tek başına sıralı kısımdır; geri kalanı sırasız.

i = 1i301152236445← sıralısırasız →gecici1

Sırasız kısmın ilk elemanı alınır: gecici = 1.

i = 1j303152236445← sıralısırasız →gecici1

3 > 1 → 3 bir sağa kaydırılır (indis 0 → 1).

i = 1j+1103152236445← sıralısırasız →

Dizinin başına gelindi → 1 indis 0'a yerleştirilir (1 kaydırma).

i = 2i103152236445← sıralısırasız →gecici5

Sırasız kısmın ilk elemanı alınır: gecici = 5.

i = 2j+1103152236445← sıralısırasız →

3 ≤ 5 → 5 indis 2'ye yerleştirilir (kaydırma gerekmedi).

i = 3i103152236445← sıralısırasız →gecici2

Sırasız kısmın ilk elemanı alınır: gecici = 2.

i = 3j103152536445← sıralısırasız →gecici2

5 > 2 → 5 bir sağa kaydırılır (indis 2 → 3).

i = 3j103132536445← sıralısırasız →gecici2

3 > 2 → 3 bir sağa kaydırılır (indis 1 → 2).

i = 3j+1102132536445← sıralısırasız →

1 ≤ 2 → 2 indis 1'e yerleştirilir (2 kaydırma).

i = 4i102132536445← sıralısırasız →gecici6

Sırasız kısmın ilk elemanı alınır: gecici = 6.

i = 4j+1102132536445← sıralısırasız →

5 ≤ 6 → 6 indis 4'e yerleştirilir (kaydırma gerekmedi).

i = 5i102132536445← sıralısırasız →gecici4

Sırasız kısmın ilk elemanı alınır: gecici = 4.

i = 5j102132536465← sıralıgecici4

6 > 4 → 6 bir sağa kaydırılır (indis 4 → 5).

i = 5j102132535465← sıralıgecici4

5 > 4 → 5 bir sağa kaydırılır (indis 3 → 4).

i = 5j+1102132435465← sıralı

3 ≤ 4 → 4 indis 3'e yerleştirilir (2 kaydırma). Dizi sıralı: [1, 2, 3, 4, 5, 6].

Eklemeli Sıralama

Eklemeli Sıralama: Java Kodu

for(int i = 1; i < n; i++) {
  int gecici = dizi[i];
  int j = i - 1;
  while(j >= 0 && dizi[j] > gecici) {
    dizi[j+1] = dizi[j];
    j = j - 1;
  }
  dizi[j+1] = gecici;
}
  • i = 1'den başlanır: tek elemanlı dizi[0..0] zaten sıralıdır.
  • gecici: yerleştirilecek eleman (anahtar). Kaydırmalar onun hücresinin üzerine yazacağı için önce saklanır.
  • while: soldaki eleman büyük olduğu sürece onu bir sağa kaydır.
  • Döngü bitince boşalan yer j + 1'dir.
Yer değiştirme (swap) değil kaydırma yapılır: her adımda 3 yerine 1 atama. Bu yüzden eklemeli sıralama kabarcıktan belirgin biçimde hızlıdır.

Eklemeli Sıralama · Kodu adım adım çalıştır

Eklemeli Sıralama: Kodu İzle, dizi = [5, 1, 9, 2, 10]

dizi[]50119223104← sıralısırasız →

n = 5. Sıralı kısım: yalnızca dizi[0].

dizi[]ij50119223104← sıralısırasız →gecici1

i = 1: gecici = dizi[1] = 1, j = 0.

dizi[]j50119223104← sıralısırasız →gecici1

j = 0 ≥ 0 ve dizi[0] = 5 > 1 → döngüye gir.

dizi[]j+150519223104← sıralısırasız →gecici1

dizi[1] = dizi[0] = 5 (sağa kaydır), j = -1.

dizi[]50519223104← sıralısırasız →gecici1

j = −1: döngü biter.

dizi[]j+110519223104← sıralısırasız →

dizi[0] = gecici = 1. Sıralı kısım: [1, 5].

dizi[]ij10519223104← sıralısırasız →gecici9

i = 2: gecici = dizi[2] = 9, j = 1.

dizi[]j10519223104← sıralısırasız →gecici9

dizi[1] = 5 ≤ 9: döngü biter.

dizi[]j+110519223104← sıralısırasız →

dizi[2] = gecici = 9. Sıralı kısım: [1, 5, 9].

dizi[]ij10519223104← sıralısırasız →gecici2

i = 3: gecici = dizi[3] = 2, j = 2.

dizi[]j10519223104← sıralısırasız →gecici2

j = 2 ≥ 0 ve dizi[2] = 9 > 2 → döngüye gir.

dizi[]j+110519293104← sıralısırasız →gecici2

dizi[3] = dizi[2] = 9 (sağa kaydır), j = 1.

dizi[]j10519293104← sıralısırasız →gecici2

j = 1 ≥ 0 ve dizi[1] = 5 > 2 → döngüye gir.

dizi[]j+110515293104← sıralısırasız →gecici2

dizi[2] = dizi[1] = 5 (sağa kaydır), j = 0.

dizi[]j10515293104← sıralısırasız →gecici2

dizi[0] = 1 ≤ 2: döngü biter.

dizi[]j+110215293104← sıralısırasız →

dizi[1] = gecici = 2. Sıralı kısım: [1, 2, 5, 9].

dizi[]ij10215293104← sıralısırasız →gecici10

i = 4: gecici = dizi[4] = 10, j = 3.

dizi[]j10215293104← sıralıgecici10

dizi[3] = 9 ≤ 10: döngü biter.

dizi[]j+110215293104← sıralı

dizi[4] = gecici = 10. Sıralı kısım: [1, 2, 5, 9, 10].

dizi[]10215293104

i = 5 < n değil → döngü biter. Sonuç: [1, 2, 5, 9, 10].

for(int i = 1; i < n; i++) {
  int gecici = dizi[i];
  int j = i - 1;
  while(j >= 0 && dizi[j] > gecici) {
    dizi[j+1] = dizi[j];
    j = j - 1;
  }
  dizi[j+1] = gecici;
}

Eklemeli Sıralama

Eklemeli Sıralama: Analiz

DurumGirdiKarşılaştırmaKaydırmaZaman
En iyisıralın − 10Θ(n)
Ortalamarastgele≈ n²/4≈ n²/4Θ(n²)
En kötüters sıralın(n − 1)/2n(n − 1)/2Θ(n²)
Artıları
  • Kararlı, yerinde, çevrimiçi.
  • Uyarlanabilir: süre Θ(n + ters çift sayısı).
  • Küçük dizilerde (n ≲ 20–50) en hızlılardan.
Eksileri
  • Rastgele büyük dizilerde Θ(n²).
  • Bir eleman tek adımda yalnızca bir hücre ilerler; uzaktaki eleman çok kaydırma ister (→ kabuk sıralama).

Bu yüzden Timsort ve birçok kütüphane, hızlı/birleştirmeli sıralamada küçük alt dizileri eklemeli sıralamaya bırakır.

Seçmeli Sıralama

Seçmeli Sıralama (Selection Sort)

  • Dizi iki bölüme ayrılır: sıralı ve sırasız.
  • Her adımda:
    • Sırasız bölümden en küçük eleman bulunur.
    • Sırasız bölümün başındaki eleman ile yer değiştirilir.
    • Yer değiştirmenin ardından sıralı bölümün parçası olur.
  • Toplam n − 1 tur; her tur en fazla bir yer değiştirme.
en küçük102152336445yer değiştir← sıralısırasız →

Seçmeli Sıralama · Adım adım

Seçmeli Sıralama Adım Adım: [3, 1, 5, 2, 6, 4]

Başlangıç301152236445sırasız →

Dizi [3, 1, 5, 2, 6, 4], uzunluk = 6. Başta sıralı kısım boştur.

1. Turen küçük301152236445sırasız →en küçük3

1. tur: sırasız kısmın ilk elemanı geçici en küçük kabul edilir: en küçük = 3.

1. Turen küçük301152236445sırasız →en küçük1

1 < en küçük (3)? Evet → en küçük = 1.

1. Turen küçükj301152236445sırasız →en küçük1

5 < en küçük (1)? Hayır.

1. Turen küçükj301152236445sırasız →en küçük1

2 < en küçük (1)? Hayır.

1. Turen küçükj301152236445sırasız →en küçük1

6 < en küçük (1)? Hayır.

1. Turen küçükj301152236445sırasız →en küçük1

4 < en küçük (1)? Hayır.

1. Tur103152236445yer değiştirsırasız →

En küçük (1) sırasız kısmın başıyla yer değiştirir → [1, 3, 5, 2, 6, 4]; sıralı kısım bir büyür.

2. Turen küçük103152236445← sıralısırasız →en küçük3

2. tur: sırasız kısmın ilk elemanı geçici en küçük kabul edilir: en küçük = 3.

2. Turen küçükj103152236445← sıralısırasız →en küçük3

5 < en küçük (3)? Hayır.

2. Turen küçük103152236445← sıralısırasız →en küçük2

2 < en küçük (3)? Evet → en küçük = 2.

2. Turen küçükj103152236445← sıralısırasız →en küçük2

6 < en küçük (2)? Hayır.

2. Turen küçükj103152236445← sıralısırasız →en küçük2

4 < en küçük (2)? Hayır.

2. Tur102152336445yer değiştir← sıralısırasız →

En küçük (2) sırasız kısmın başıyla yer değiştirir → [1, 2, 5, 3, 6, 4]; sıralı kısım bir büyür.

3. Turen küçük102152336445← sıralısırasız →en küçük5

3. tur: sırasız kısmın ilk elemanı geçici en küçük kabul edilir: en küçük = 5.

3. Turen küçük102152336445← sıralısırasız →en küçük3

3 < en küçük (5)? Evet → en küçük = 3.

3. Turen küçükj102152336445← sıralısırasız →en küçük3

6 < en küçük (3)? Hayır.

3. Turen küçükj102152336445← sıralısırasız →en küçük3

4 < en küçük (3)? Hayır.

3. Tur102132536445yer değiştir← sıralısırasız →

En küçük (3) sırasız kısmın başıyla yer değiştirir → [1, 2, 3, 5, 6, 4]; sıralı kısım bir büyür.

4. Turen küçük102132536445← sıralısırasız →en küçük5

4. tur: sırasız kısmın ilk elemanı geçici en küçük kabul edilir: en küçük = 5.

4. Turen küçükj102132536445← sıralısırasız →en küçük5

6 < en küçük (5)? Hayır.

4. Turen küçük102132536445← sıralısırasız →en küçük4

4 < en küçük (5)? Evet → en küçük = 4.

4. Tur102132436455yer değiştir← sıralısırasız →

En küçük (4) sırasız kısmın başıyla yer değiştirir → [1, 2, 3, 4, 6, 5]; sıralı kısım bir büyür.

5. Turen küçük102132436455← sıralısırasız →en küçük6

5. tur: sırasız kısmın ilk elemanı geçici en küçük kabul edilir: en küçük = 6.

5. Turen küçük102132436455← sıralısırasız →en küçük5

5 < en küçük (6)? Evet → en küçük = 5.

5. Tur102132435465yer değiştir← sıralısırasız →

En küçük (5) sırasız kısmın başıyla yer değiştirir → [1, 2, 3, 4, 5, 6]; sıralı kısım bir büyür.

Sonuç102132435465

5 tur sonunda son eleman kendiliğinden yerindedir. Sıralı dizi: [1, 2, 3, 4, 5, 6].

Seçmeli Sıralama

Seçmeli Sıralama: Java Kodu

public void sirala(int[] dizi) {
  int n = dizi.length;
  for(int i = 0; i < n - 1; i++) {
    int enKucuk = i;
    for(int j = i + 1; j < n; j++) {
      if(dizi[j] < dizi[enKucuk]) {
        enKucuk = j;
      }
    }
    int gecici = dizi[enKucuk];
    dizi[enKucuk] = dizi[i];
    dizi[i] = gecici;
  }
}
  • enKucuk en küçük elemanın indisini tutar (değerini değil): sonunda yer değiştirmek için indis gerekir.
  • İç döngü sırasız kısmın tamamını tarar; girdi sıralı olsa bile tarama kısalmaz.
  • Tur başına bir yer değiştirme: toplam en fazla n − 1.
Yazma işleminin pahalı olduğu ortamlarda (ör. flash bellek) az sayıda yer değiştirme seçmeli sıralamanın tek gerçek avantajıdır.

Seçmeli Sıralama · Kodu adım adım çalıştır

Seçmeli Sıralama: Kodu İzle, dizi = [5, 1, 10, 2, 9]

dizi[]50111022394

n = dizi.length = 5.

dizi[]i, enKucuk50111022394sırasız →

i = 0: enKucuk = 0 (dizi[enKucuk] = 5).

dizi[]enKucukj50111022394sırasız →

j = 1: dizi[1] = 1 < dizi[enKucuk] = 5? Evet.

dizi[]enKucuk, j50111022394sırasız →

enKucuk = 1 (yeni en küçük: 1).

dizi[]enKucukj50111022394sırasız →

j = 2: dizi[2] = 10 < dizi[enKucuk] = 1? Hayır.

dizi[]enKucukj50111022394sırasız →

j = 3: dizi[3] = 2 < dizi[enKucuk] = 1? Hayır.

dizi[]enKucukj50111022394sırasız →

j = 4: dizi[4] = 9 < dizi[enKucuk] = 1? Hayır.

dizi[]ienKucuk10511022394yer değiştirsırasız →

j = 5 → iç döngü biter. gecici = 1; dizi[1] ↔ dizi[0] → [1, 5, 10, 2, 9].

dizi[]i, enKucuk10511022394← sıralısırasız →

i = 1: enKucuk = 1 (dizi[enKucuk] = 5).

dizi[]enKucukj10511022394← sıralısırasız →

j = 2: dizi[2] = 10 < dizi[enKucuk] = 5? Hayır.

dizi[]enKucukj10511022394← sıralısırasız →

j = 3: dizi[3] = 2 < dizi[enKucuk] = 5? Evet.

dizi[]enKucuk, j10511022394← sıralısırasız →

enKucuk = 3 (yeni en küçük: 2).

dizi[]enKucukj10511022394← sıralısırasız →

j = 4: dizi[4] = 9 < dizi[enKucuk] = 2? Hayır.

dizi[]ienKucuk10211025394yer değiştir← sıralısırasız →

j = 5 → iç döngü biter. gecici = 2; dizi[3] ↔ dizi[1] → [1, 2, 10, 5, 9].

dizi[]i, enKucuk10211025394← sıralısırasız →

i = 2: enKucuk = 2 (dizi[enKucuk] = 10).

dizi[]enKucukj10211025394← sıralısırasız →

j = 3: dizi[3] = 5 < dizi[enKucuk] = 10? Evet.

dizi[]enKucuk, j10211025394← sıralısırasız →

enKucuk = 3 (yeni en küçük: 5).

dizi[]enKucukj10211025394← sıralısırasız →

j = 4: dizi[4] = 9 < dizi[enKucuk] = 5? Hayır.

dizi[]ienKucuk10215210394yer değiştir← sıralısırasız →

j = 5 → iç döngü biter. gecici = 5; dizi[3] ↔ dizi[2] → [1, 2, 5, 10, 9].

dizi[]i, enKucuk10215210394← sıralısırasız →

i = 3: enKucuk = 3 (dizi[enKucuk] = 10).

dizi[]enKucukj10215210394← sıralısırasız →

j = 4: dizi[4] = 9 < dizi[enKucuk] = 10? Evet.

dizi[]enKucuk, j10215210394← sıralısırasız →

enKucuk = 4 (yeni en küçük: 9).

dizi[]ienKucuk10215293104yer değiştir← sıralısırasız →

j = 5 → iç döngü biter. gecici = 9; dizi[4] ↔ dizi[3] → [1, 2, 5, 9, 10].

dizi[]10215293104

i = 4 < n − 1 değil → biter. Sonuç: [1, 2, 5, 9, 10].

public void sirala(int[] dizi) {
  int n = dizi.length;
  for(int i = 0; i < n - 1; i++) {
    int enKucuk = i;
    for(int j = i + 1; j < n; j++) {
      if(dizi[j] < dizi[enKucuk]) {
        enKucuk = j;
      }
    }
    int gecici = dizi[enKucuk];
    dizi[enKucuk] = dizi[i];
    dizi[i] = gecici;
  }
}

Seçmeli Sıralama

Seçmeli Sıralama: Analiz

ÖlçüDeğer
Karşılaştırma(n − 1) + (n − 2) + … + 1 = n(n − 1)/2, her girdide
Yer değiştirmeen fazla n − 1
Zamanen iyi = ortalama = en kötü = Θ(n²)
Ek bellekO(1), yerinde
Kararlı mı?Hayır (uzun mesafeli takas)
Girdi2ₐ2ᵦ11. tur: takasÇıktı12ᵦ2ₐ

En küçük (1), baştaki 2ₐ ile yer değiştirir: 2ₐ, 2ᵦ'nin arkasına geçer.

Uyarlanabilir değildir: sıralı bir diziye de n(n − 1)/2 karşılaştırma harcar.

Basit Algoritmalar · Karşılaştırma

Kabarcık, Eklemeli, Seçmeli: Aynı Girdide

Hücreler: karşılaştırma / yer değiştirme (ya da kaydırma) sayısı, n = 6. Değerler kodlar çalıştırılarak sayılmıştır.

AlgoritmaTaşıma türü[3, 1, 5, 2, 6, 4]sıralı 1…6ters 6…1
Kabarcık (bayraklı)takas12 / 55 / 015 / 15
Eklemelikaydırma9 / 55 / 015 / 15
Seçmelitakas15 / 515 / 015 / 3
  • Kabarcık ve eklemeli sıralamada taşıma sayısı = ters çift sayısı ([3, 1, 5, 2, 6, 4] için 5); bir takas 3, bir kaydırma 1 atamadır.
  • Seçmeli sıralama girdiden bağımsız olarak hep n(n − 1)/2 = 15 karşılaştırma yapar ama en az yer değiştirmeyi o yapar.
  • Sıralı girdide bayraklı kabarcık ve eklemeli yalnızca n − 1 = 5 karşılaştırma yapar (uyarlanabilir).

Kabuk Sıralama

Kabuk Sıralama (Shell Sort)

  • D. Shell (1959): eklemeli sıralamanın genelleştirilmesi.
  • Önce birbirinden aralık (gap) uzaklıktaki elemanlar eklemeli sıralanır; uzaktaki küçük elemanlar tek hamlede büyük mesafe atlar.
  • Aralık küçültülür (n/2, n/4, …); son tur aralık = 1, yani sıradan eklemeli sıralama — ama dizi artık neredeyse sıralıdır.
  • Yerinde, kararsız; süre aralık dizisine bağlı: n/2 aralıklarıyla en kötü Θ(n²), Hibbard (2ᵏ − 1) ile O(n1,5).
void kabukSirala(int[] dizi) {
  int n = dizi.length;
  for (int aralik = n / 2; aralik > 0; aralik /= 2)
    for (int i = aralik; i < n; i++) {
      int gecici = dizi[i], j;
      for (j = i; j >= aralik && dizi[j - aralik] > gecici; j -= aralik)
        dizi[j] = dizi[j - aralik];
      dizi[j] = gecici;
    }
}

Kabuk Sıralama · Adım adım

Kabuk Sıralama Adım Adım: [6, 5, 3, 1, 8, 7, 2, 4]

Başlangıç6051321384752647

Dizi [6, 5, 3, 1, 8, 7, 2, 4], n = 8. Aralık dizisi: n/2 = 4, 2, … , 1.

aralik = 4: gruplar6051321384752647

aralik = 4: aralarında 4 indis olan elemanlar aynı grupta (aynı renk): [6, 8], [5, 7], [3, 2], [1, 4].

aralik = 4: sonra6051221384753647

Her grup eklemeli sıralamayla sıralandı (1 kaydırma): [6, 8], [5, 7], [2, 3], [1, 4] → [6, 5, 2, 1, 8, 7, 3, 4].

aralik = 2: gruplar6051221384753647

aralik = 2: aralarında 2 indis olan elemanlar aynı grupta (aynı renk): [6, 2, 8, 3], [5, 1, 7, 4].

aralik = 2: sonra2011324364558677

Her grup eklemeli sıralamayla sıralandı (6 kaydırma): [2, 3, 6, 8], [1, 4, 5, 7] → [2, 1, 3, 4, 6, 5, 8, 7].

aralik = 1: gruplar2011324364558677

aralik = 1: aralarında 1 indis olan elemanlar aynı grupta (aynı renk): [2, 1, 3, 4, 6, 5, 8, 7].

aralik = 1: sonra1021324354657687

aralik = 1 sıradan eklemeli sıralamadır; dizi neredeyse sıralı olduğu için yalnızca 3 kaydırma gerekti. Sonuç: [1, 2, 3, 4, 5, 6, 7, 8].

Birleştirmeli Sıralama

Birleştirmeli Sıralama (Merge Sort)

  • Böl ve fethet (divide and conquer) yaklaşımını kullanır.
  • 1945'te John von Neumann tarafından geliştirilmiştir.
  • En kötü durumda bile O(n log n).
  • Kararlıdır; birleştirme için ek bellek (O(n)) gerekir.
Nasıl çalışır?

1. Böl (divide): liste iki alt listeye bölünür; alt listeler tek eleman kalana kadar tekrar tekrar bölünür.

2. Fethet (conquer): her yarı aynı yöntemle (özyinelemeli) sıralanır.

3. Birleştir (combine): sıralı alt listeler, sıralı tek bir liste oluşana kadar birleştirilir.

Tek elemanlı liste tanım gereği sıralıdır; bu, özyinelemenin taban durumudur. Asıl iş birleştirme adımında yapılır.

Birleştirmeli Sıralama

Örnek: [38, 27, 43, 3, 9, 82, 10]

Girdi382743398210Böl382743398210Böl382743398210Böl382743398210Birleştir273834398210Birleştir327384391082Birleştir391027384382

Yedi eleman: orta = ⌊(sol + sağ)/2⌋ olduğu için sol yarı bir eleman fazla alır ([38, 27, 43, 3] ve [9, 82, 10]).

Birleştirmeli Sıralama · Adım adım

Merge Sort Adım Adım: [6, 5, 3, 1, 8, 7, 2, 4]

65318724

Dizi [6, 5, 3, 1, 8, 7, 2, 4]: önce tek eleman kalana kadar bölünür, sonra sıralı parçalar birleştirilir.

6531872465318724

Böl: [6, 5, 3, 1, 8, 7, 2, 4] → [6, 5, 3, 1] ve [8, 7, 2, 4].

65318724653187246531

Böl: [6, 5, 3, 1] → [6, 5] ve [3, 1].

6531872465318724653165

Böl: [6, 5] → [6] ve [5]. Tek elemanlı parçalar zaten sıralıdır.

6531872465318724563165

Birleştir: [6] + [5] → [5, 6].

653187246531872456316531

Böl: [3, 1] → [3] ve [1]. Tek elemanlı parçalar zaten sıralıdır.

653187246531872456136531

Birleştir: [3] + [1] → [1, 3].

653187241356872456136531

Birleştir: [5, 6] + [1, 3] → [1, 3, 5, 6].

6531872413568724561387246531

Böl: [8, 7, 2, 4] → [8, 7] ve [2, 4].

653187241356872456138724653187

Böl: [8, 7] → [8] ve [7]. Tek elemanlı parçalar zaten sıralıdır.

653187241356872456137824653187

Birleştir: [8] + [7] → [7, 8].

65318724135687245613782465318724

Böl: [2, 4] → [2] ve [4]. Tek elemanlı parçalar zaten sıralıdır.

65318724135687245613782465318724

Birleştir: [2] + [4] → [2, 4].

65318724135624785613782465318724

Birleştir: [7, 8] + [2, 4] → [2, 4, 7, 8].

12345678135624785613782465318724

Birleştir: [1, 3, 5, 6] + [2, 4, 7, 8] → [1, 2, 3, 4, 5, 6, 7, 8]. Dizi sıralandı.

Birleştirmeli Sıralama

Merge Sort: Java Kodu

void birlestirmeliSirala(int[] dizi, int sol, int sag) {
  if (sol < sag) {
    int orta = sol + (sag - sol) / 2;
    birlestirmeliSirala(dizi, sol, orta);
    birlestirmeliSirala(dizi, orta + 1, sag);
    birlestir(dizi, sol, orta, sag);
  }
}
void birlestir(int[] A, int p, int q, int r) {
  int[] L = Arrays.copyOfRange(A, p, q + 1);
  int[] R = Arrays.copyOfRange(A, q + 1, r + 1);
  int i = 0, j = 0, k = p;
  while (i < L.length && j < R.length) {
    if (L[i] <= R[j]) A[k++] = L[i++];
    else              A[k++] = R[j++];
  }
  while (i < L.length) A[k++] = L[i++];
  while (j < R.length) A[k++] = R[j++];
}

sol + (sag − sol) / 2 yazımı, (sol + sag) / 2 toplamındaki int taşmasını önler.

Birleştirmeli Sıralama · Kodu adım adım çalıştır

birlestir(): İki Sıralı Diziyi Birleştir

L1356iR2478jA01234567k

L = A[p..q] = [1, 3, 5, 6] ve R = A[q+1..r] = [2, 4, 7, 8] kopyalanır (ikisi de sıralı). i = j = 0, k = p = 0.

L1356iR2478jA101234567k

L[0] = 1 ≤ R[0] = 2 → A[0] = 1; i++, k++.

L1356iR2478jA1021234567k

L[1] = 3 > R[0] = 2 → A[1] = 2; j++, k++.

L1356iR2478jA10213234567k

L[1] = 3 ≤ R[1] = 4 → A[2] = 3; i++, k++.

L1356iR2478jA102132434567k

L[2] = 5 > R[1] = 4 → A[3] = 4; j++, k++.

L1356iR2478jA1021324354567k

L[2] = 5 ≤ R[2] = 7 → A[4] = 5; i++, k++.

L1356R2478jA10213243546567k

L[3] = 6 ≤ R[2] = 7 → A[5] = 6; i++, k++.

L1356R2478jA102132435465767k

L bitti (i = 4); kalan R elemanları sırayla kopyalanır: A[6] = 7.

L1356R2478A1021324354657687

A[7] = 8. Birleştirme bitti: [1, 2, 3, 4, 5, 6, 7, 8] (8 eleman, en fazla 7 karşılaştırma).

void birlestir(int[] A, int p, int q, int r) {
  int[] L = Arrays.copyOfRange(A, p, q + 1);
  int[] R = Arrays.copyOfRange(A, q + 1, r + 1);
  int i = 0, j = 0, k = p;
  while (i < L.length && j < R.length) {
    if (L[i] <= R[j]) A[k++] = L[i++];
    else              A[k++] = R[j++];
  }
  while (i < L.length) A[k++] = L[i++];
  while (j < R.length) A[k++] = R[j++];
}

Birleştirmeli Sıralama

Merge Sort: Analiz

Yineleme bağıntısı (recurrence):

T(n) = 2 T(n/2) + Θ(n)

  • Her düzeyde toplam birleştirme işi Θ(n).
  • Düzey sayısı log₂ n (n'yi 1'e kadar yarılamak).
  • Toplam: Θ(n log n) — en iyi = ortalama = en kötü.
  • Ek bellek Θ(n) (yardımcı diziler) + Θ(log n) özyineleme yığını.
  • L[i] <= R[j]: eşitlikte soldan alınır → kararlı.
nnn/2n/2nn/4n/4n/4n/4n⋮⋮11111111nΣ = n · log₂ nlog₂ n düzey
Ana teoremle (Bölüm 1.2): a = 2, b = 2, f(n) = Θ(n) = Θ(nlog₂ 2) → 2. durum → T(n) = Θ(n log n).

Hızlı Sıralama

Hızlı Sıralama (Quick Sort)

  • C. A. R. Hoare (1959). Yine böl ve fethet, ama işin çoğu bölmede yapılır.
  • Bir pivot eleman seçilir.
  • Dizi pivot etrafında iki parçaya bölünür (parçalama, partitioning): solda ≤ x, sağda ≥ x.
  • İki alt parça özyinelemeli olarak sıralanır. Birleştirme adımına gerek yoktur.
≤ xx≥ xpivotsol parça → özyinelemeli sıralasağ parça → özyinelemeli sırala
Parçalamadan sonra pivot kesin yerindedir: sıralı dizide de tam o indiste duracaktır.

Hızlı Sıralama

Parçalama (Partitioning) Prosedürü

Lomuto: pivot = son eleman

parcala(A, p, q):
  pivot = A[q]        // pivot seç
  i = p - 1           // ≤ pivot bölgesinin sonu
  for j = p to q - 1:
    if A[j] <= pivot:
      i = i + 1
      takas(A[i], A[j])
  takas(A[i + 1], A[q])  // pivotu yerleştir
  return i + 1          // pivotun indisi

Aynı fikir: pivot = ilk eleman

PARCALA(A, p, q):
  x = A[p]            // pivot
  i = p
  for j = p + 1 to q:
    if A[j] <= x:
      i = i + 1
      takas(A[i], A[j])
  takas(A[p], A[i])
  return i

Değişmez (invariant): A[p..i] ≤ pivot, A[i+1..j−1] > pivot, A[j..] henüz incelenmedi. Tek geçiş: Θ(n) zaman, O(1) ek bellek. Sonraki örnek sağdaki sürümü, kod izleme soldakini kullanır.

Hızlı Sıralama · Adım adım

Parçalara Ayırma: [6, 10, 13, 5, 8, 3, 2, 11]

x = A[p] = 6ij6010113253843526117

Pivot x = A[p] = 6 (sarı). i = p; j, p + 1'den başlar. Mavi: ≤ x, kırmızı: > x, beyaz: henüz bakılmadı.

j = 1ij6010113253843526117

A[j] = 10 > 6 → yalnızca j ilerler; kırmızı bölge büyür.

j = 2ij6010113253843526117

A[j] = 13 > 6 → yalnızca j ilerler; kırmızı bölge büyür.

j = 3ij6051132103843526117takas

A[j] = 5 ≤ 6 → i = 1; A[i] ↔ A[j]: [6, 5, 13, 10, 8, 3, 2, 11]. Mavi bölge bir büyüdü.

j = 4ij6051132103843526117

A[j] = 8 > 6 → yalnızca j ilerler; kırmızı bölge büyür.

j = 5ij6051321038413526117takas

A[j] = 3 ≤ 6 → i = 2; A[i] ↔ A[j]: [6, 5, 3, 10, 8, 13, 2, 11]. Mavi bölge bir büyüdü.

j = 6ij6051322384135106117takas

A[j] = 2 ≤ 6 → i = 3; A[i] ↔ A[j]: [6, 5, 3, 2, 8, 13, 10, 11]. Mavi bölge bir büyüdü.

j = 7ij6051322384135106117

A[j] = 11 > 6 → yalnızca j ilerler; kırmızı bölge büyür.

Son: A[p] ↔ A[i]i2051326384135106117takas

Döngü bitti. Pivot, mavi bölgenin son elemanıyla yer değiştirir: [2, 5, 3, 6, 8, 13, 10, 11]. Pivot 6 artık kesin yerinde (indis 3); solu ≤ 6, sağı ≥ 6.

Hızlı Sıralama · Kodu adım adım çalıştır

parcala(): Kodu İzle, dizi = [2, 8, 7, 1, 3, 5, 6, 4]

dizi[]2081721334556647

pivot = dizi[ust] = 4; i = alt − 1 = −1 (≤ pivot bölgesi boş).

dizi[]j2081721334556647

j = 0: dizi[0] = 2 ≤ 4? Evet.

dizi[]i, j2081721334556647

i = 0; takas(dizi, 0, 0) → [2, 8, 7, 1, 3, 5, 6, 4] (kendisiyle).

dizi[]ij2081721334556647

j = 1: dizi[1] = 8 ≤ 4? Hayır → j ilerler.

dizi[]ij2081721334556647

j = 2: dizi[2] = 7 ≤ 4? Hayır → j ilerler.

dizi[]ij2081721334556647

j = 3: dizi[3] = 1 ≤ 4? Evet.

dizi[]ij2011728334556647takas

i = 1; takas(dizi, 1, 3) → [2, 1, 7, 8, 3, 5, 6, 4].

dizi[]ij2011728334556647

j = 4: dizi[4] = 3 ≤ 4? Evet.

dizi[]ij2011328374556647takas

i = 2; takas(dizi, 2, 4) → [2, 1, 3, 8, 7, 5, 6, 4].

dizi[]ij2011328374556647

j = 5: dizi[5] = 5 ≤ 4? Hayır → j ilerler.

dizi[]ij2011328374556647

j = 6: dizi[6] = 6 ≤ 4? Hayır → j ilerler.

dizi[]i2011324374556687takas

Döngü bitti. takas(dizi, i+1 = 3, ust = 7) → [2, 1, 3, 4, 7, 5, 6, 8].

dizi[]i2011324374556687

return 3: pivot 4 kesin yerinde; sol [0..2] ≤ 4, sağ [4..7] > 4.

int parcala(int[] dizi, int alt, int ust) {
  int pivot = dizi[ust];
  int i = alt - 1;
  for (int j = alt; j < ust; j++) {
    if (dizi[j] <= pivot) {
      i++;
      takas(dizi, i, j);
    }
  }
  takas(dizi, i + 1, ust);
  return i + 1;
}

Hızlı Sıralama

QuickSort: Özyinelemeli Yapı

HIZLI-SIRALA(A, p, r)
  if p < r
    q = PARCALA(A, p, r)
    HIZLI-SIRALA(A, p, q − 1)
    HIZLI-SIRALA(A, q + 1, r)

İlk çağrı: HIZLI-SIRALA(A, 1, n)
void hizliSirala(int[] dizi, int alt, int ust) {
  if (alt < ust) {
    int p = parcala(dizi, alt, ust);
    hizliSirala(dizi, alt, p - 1);
    hizliSirala(dizi, p + 1, ust);
  }
}
  • Pivot (indis q) iki özyinelemeli çağrının hiçbirine dahil edilmez: yerine oturmuştur.
  • Taban durumu: 0 ya da 1 elemanlı alt dizi (p ≥ r) zaten sıralıdır.
  • Java sürümü 0-tabanlıdır: ilk çağrı hizliSirala(dizi, 0, n − 1).

Hızlı Sıralama · Adım adım

QuickSort Adım Adım: [6, 10, 13, 5, 8, 3, 2, 11]

HIZLI-SIRALA(A, 0, 7)6010113253843526117

Dizi [6, 10, 13, 5, 8, 3, 2, 11]. Her çağrı alt diziyi pivot = ilk eleman ile parçalar, sonra iki tarafı özyinelemeli sıralar.

HIZLI-SIRALA(A, 0, 7)q2051326384135106117

Derinlik 0: [6, 10, 13, 5, 8, 3, 2, 11] pivot 6 ile parçalanır → pivot indis 3'e oturur; sonra [0..2] ve [4..7] sıralanır.

HIZLI-SIRALA(A, 0, 2)q2051326384135106117

Derinlik 1: [2, 5, 3] pivot 2 ile parçalanır → pivot indis 0'a oturur; sonra [0..-1] ve [1..2] sıralanır.

HIZLI-SIRALA(A, 1, 2)q2031526384135106117

Derinlik 2: [5, 3] pivot 5 ile parçalanır → pivot indis 2'ye oturur; sonra [1..1] ve [3..2] sıralanır.

HIZLI-SIRALA(A, 1, 1)q2031526384135106117

Derinlik 3: [1..1] tek elemanlı (3) → zaten sıralı (p < r değil).

HIZLI-SIRALA(A, 4, 7)q2031526384135106117

Derinlik 1: [8, 13, 10, 11] pivot 8 ile parçalanır → pivot indis 4'e oturur; sonra [4..3] ve [5..7] sıralanır.

HIZLI-SIRALA(A, 5, 7)q2031526384115106137

Derinlik 2: [13, 10, 11] pivot 13 ile parçalanır → pivot indis 7'ye oturur; sonra [5..6] ve [8..7] sıralanır.

HIZLI-SIRALA(A, 5, 6)q2031526384105116137

Derinlik 3: [11, 10] pivot 11 ile parçalanır → pivot indis 6'ya oturur; sonra [5..5] ve [7..6] sıralanır.

HIZLI-SIRALA(A, 5, 5)q2031526384105116137

Derinlik 4: [5..5] tek elemanlı (10) → zaten sıralı (p < r değil).

Sonuç2031526384105116137

Tüm çağrılar bitti; birleştirme adımı yok, dizi yerinde sıralandı: [2, 3, 5, 6, 8, 10, 11, 13].

Hızlı Sıralama

QuickSort: Analiz ve Pivot Seçimi

DurumNe zaman?YinelemeZaman
En iyipivot her seferinde ortancaT(n) = 2T(n/2) + Θ(n)Θ(n log n)
Ortalamarastgele girdi / rastgele pivotbeklenen ≈ 1,39 n log₂ n karşılaştırmaΘ(n log n)
En kötüpivot hep en küçük/en büyük (ör. sıralı dizi + son eleman pivot)T(n) = T(n − 1) + Θ(n)Θ(n²)
Rastgele pivotPivotu rastgele seçmek kötü girdiyi olanaksız kılar; beklenen süre her girdide Θ(n log n).
Üçün ortancasıİlk, orta ve son elemanın ortancası pivot olur; sıralı girdide en kötü durumu önler.
Küçük parçalarn ≲ 16 olunca eklemeli sıralamaya geçmek ve küçük tarafa önce inmek (yığın O(log n)) pratikte hızlandırır.

Yerinde (O(log n) ortalama yığın), kararsız. Önbellek dostu olduğu için pratikte genellikle en hızlı karşılaştırmalı sıralamadır (Java Arrays.sort(int[]): çift pivotlu quicksort).

Yığın Sıralama

Yığın Sıralama (Heap Sort)

  • Yığın (heap) veri yapısını kullanarak sıralar; ortalama ve en kötü durumda O(n log n).
  • Max-heap: her düğüm çocuklarından büyük ya da eşittir → en büyük eleman köktedir.
  • Ağaç ayrı bir yapı değildir; dizinin kendisidir: dizi[i]'nin çocukları 2i + 1 ve 2i + 2, ebeveyni (i − 1) / 2.
İşleyiş
  1. Dizi max-heap yapısına dönüştürülür.
  2. En büyük eleman (kök) dizinin sonuna yerleştirilir.
  3. Kalan dizi tekrar max-heap yapılır (kök aşağı süzülür).
  4. Tüm elemanlar sıralanana kadar tekrarlanır.
1005132431410051324314dizi

Yığın Sıralama

Örnek: [4, 10, 3, 5, 1]

AdımDizi (yığın | sıralı)Açıklama
Dizi[4, 10, 3, 5, 1]
Max-heap oluştur[10, 5, 3, 4, 1]kök = en büyük
Kök ↔ dizi[4][1, 5, 3, 4] | [10]10 sıralı bölgeye
Yeniden yığınlaştır[5, 4, 3, 1] | [10]kök aşağı süzüldü
Kök ↔ dizi[3][1, 4, 3] | [5, 10]5 sıralı bölgeye
Yeniden yığınlaştır[4, 1, 3] | [5, 10]kök aşağı süzüldü
Kök ↔ dizi[2][3, 1] | [4, 5, 10]4 sıralı bölgeye
Yeniden yığınlaştır[3, 1] | [4, 5, 10]kök aşağı süzüldü
Kök ↔ dizi[1][1] | [3, 4, 5, 10]3 sıralı bölgeye
Sonuç[1, 3, 4, 5, 10]

Yığın Sıralama · Adım adım

1. Aşama: Max-Heap Kurma — [6, 5, 3, 1, 8, 7, 2, 4]

60513213847526476051321384752647dizi

Dizi [6, 5, 3, 1, 8, 7, 2, 4] tam ikili ağaç olarak düşünülür: dizi[i]'nin çocukları 2i+1 ve 2i+2. Henüz yığın (heap) değil.

60513243847526176051324384752617dizi

yiginlastir(i = 3): 1 çocuklarından küçük → yer değiştir (1 ↔ 4). Dizi: [6, 5, 3, 4, 8, 7, 2, 1].

60517243843526176051724384352617dizi

yiginlastir(i = 2): 3 çocuklarından küçük → yer değiştir (3 ↔ 7). Dizi: [6, 5, 7, 4, 8, 3, 2, 1].

60817243543526176081724354352617dizi

yiginlastir(i = 1): 5 çocuklarından küçük → yer değiştir (5 ↔ 8). Dizi: [6, 8, 7, 4, 5, 3, 2, 1].

80617243543526178061724354352617dizi

yiginlastir(i = 0): 6 çocuklarından küçük → yer değiştir (6 ↔ 8). Dizi: [8, 6, 7, 4, 5, 3, 2, 1].

80617243543526178061724354352617dizi

Yaprak olmayan tüm düğümler (i = 3 … 0) işlendi: max-heap [8, 6, 7, 4, 5, 3, 2, 1]. En büyük eleman (8) kökte.

Yığın Sıralama · Adım adım

2. Aşama: Kökü Sona Taşı, Süz

80617243543526178061724354352617dizi

Max-heap: [8, 6, 7, 4, 5, 3, 2, 1]. Her turda kök (en büyük) yığının son elemanıyla yer değiştirir ve yığın bir küçülür.

106172435435261061724354352687dizi

Kök 8 ↔ dizi[7] = 1: 8 sıralı bölgeye (yeşil) geçti. Yığın boyutu 7.

706132435415267061324354152687dizi

yiginlastir(0) ile kök aşağı süzülür (1 ↔ 7; 1 ↔ 3) → yığın: [7, 6, 3, 4, 5, 1, 2].

2061324354152061324354157687dizi

Kök 7 ↔ dizi[6] = 2: 7 sıralı bölgeye (yeşil) geçti. Yığın boyutu 6.

6051324324156051324324157687dizi

yiginlastir(0) ile kök aşağı süzülür (2 ↔ 6; 2 ↔ 5) → yığın: [6, 5, 3, 4, 2, 1].

10513243241051324324657687dizi

Kök 6 ↔ dizi[5] = 1: 6 sıralı bölgeye (yeşil) geçti. Yığın boyutu 5.

50413213245041321324657687dizi

yiginlastir(0) ile kök aşağı süzülür (1 ↔ 5; 1 ↔ 4) → yığın: [5, 4, 3, 1, 2].

204132132041321354657687dizi

Kök 5 ↔ dizi[4] = 2: 5 sıralı bölgeye (yeşil) geçti. Yığın boyutu 4.

402132134021321354657687dizi

yiginlastir(0) ile kök aşağı süzülür (2 ↔ 4) → yığın: [4, 2, 3, 1].

1021321021324354657687dizi

Kök 4 ↔ dizi[3] = 1: 4 sıralı bölgeye (yeşil) geçti. Yığın boyutu 3.

3021123021124354657687dizi

yiginlastir(0) ile kök aşağı süzülür (1 ↔ 3) → yığın: [3, 2, 1].

10211021324354657687dizi

Kök 3 ↔ dizi[2] = 1: 3 sıralı bölgeye (yeşil) geçti. Yığın boyutu 2.

20112011324354657687dizi

yiginlastir(0) ile kök aşağı süzülür (1 ↔ 2) → yığın: [2, 1].

101021324354657687dizi

Kök 2 ↔ dizi[1] = 1: 2 sıralı bölgeye (yeşil) geçti. Yığın boyutu 1.

101021324354657687dizi

Yığında tek eleman kaldı; o da yerinde. Sıralı dizi: [1, 2, 3, 4, 5, 6, 7, 8].

Yığın Sıralama

Heap Sort: Java Kodu ve Analiz

void yiginSirala(int[] dizi) {
  int n = dizi.length;
  for (int i = n / 2 - 1; i >= 0; i--)   // 1) yığın kur
    yiginlastir(dizi, n, i);
  for (int i = n - 1; i > 0; i--) {      // 2) sırala
    takas(dizi, 0, i);                   // en büyüğü sona
    yiginlastir(dizi, i, 0);             // kökü süz
  }
}
void yiginlastir(int[] dizi, int n, int i) {
  int enBuyuk = i, sol = 2 * i + 1, sag = 2 * i + 2;
  if (sol < n && dizi[sol] > dizi[enBuyuk]) enBuyuk = sol;
  if (sag < n && dizi[sag] > dizi[enBuyuk]) enBuyuk = sag;
  if (enBuyuk != i) {
    takas(dizi, i, enBuyuk);
    yiginlastir(dizi, n, enBuyuk);
  }
}
  • Yığın kurma: yapraklar (i ≥ n/2) zaten tek elemanlı yığındır; i = n/2 − 1'den köke doğru süzülür. Toplam O(n) (çoğu düğüm alçaktadır).
  • Sıralama: n − 1 kez kök sona alınır ve O(log n)'de süzülür → O(n log n).
  • En kötü durumda bile O(n log n), O(1) ek bellek (yerinde).
  • Kararsız: kök–son takası eşit anahtarların sırasını bozabilir.

Yığın, elemanları tek tek ekleyerek (yukarı süzme) de kurulabilir; bu da geçerli bir max-heap verir ama O(n log n) sürer. Buradaki aşağıdan yukarı kurma (Floyd yöntemi) O(n)'dir.

Doğrusal Zamanlı Sıralama

Karşılaştırmalı Sıralamanın Alt Sınırı

  • Yalnızca "ai ≤ aj?" sorusu soran her algoritma bir karar ağacı (decision tree) ile gösterilebilir.
  • Her yaprak bir sıralamadır (permütasyon); doğru çalışmak için n! yaprak gerekir.
  • Yüksekliği h olan ikili ağacın en fazla 2h yaprağı vardır: 2h ≥ n! ⇒ h ≥ log₂(n!) = Ω(n log n).
  • Sonuç: birleştirmeli ve yığın sıralama asimptotik olarak en iyidir.
  • Daha hızlı olmak için karşılaştırma dışında bilgi gerekir: anahtarlar küçük tamsayılar → saymalı, basamak.
≤>≤>≤>≤>≤>1:22:31:3⟨1,2,3⟩1:3⟨2,1,3⟩2:3⟨1,3,2⟩⟨3,1,2⟩⟨2,3,1⟩⟨3,2,1⟩3! = 6 yaprak → yükseklik ≥ ⌈log₂ 6⌉ = 3

Doğrusal Zamanlı Sıralama

Saymalı Sıralama (Counting Sort)

  • Elemanlar birbiriyle karşılaştırılmaz.
  • Girdi: A[1 … n], A[j] ∈ {1, 2, …, k}.
  • Çıktı: B[1 … n], sıralı.
  • Geçici: C[1 … k] sayaçları.

Fikir: anahtarı ≤ i olan eleman sayısı biliniyorsa, i anahtarlı son eleman tam o konuma yazılır.

for i = 1 to k
  C[i] = 0
for j = 1 to n
  C[A[j]] = C[A[j]] + 1   // C[i] = |{anahtar = i}|
for i = 2 to k
  C[i] = C[i] + C[i−1]    // C[i] = |{anahtar ≤ i}|
for j = n downto 1
  B[C[A[j]]] = A[j]
  C[A[j]] = C[A[j]] − 1

Doğrusal Zamanlı Sıralama · Adım adım

Saymalı Sıralama Adım Adım: A = [4, 1, 3, 4, 3]

A:4134312345C:1234B:12345

Girdi A = [4, 1, 3, 4, 3], n = 5, anahtarlar {1, …, 4}. C: sayaç dizisi (k = 4), B: çıktı.

A:4134312345C:00001234B:12345

Döngü 1: for i = 1 to k: C[i] = 0 — tüm sayaçlar sıfırlanır. Θ(k).

A:4134312345C:00011234B:12345

Döngü 2, j = 1: A[1] = 4 → C[4]++ = 1. (C[i] = i anahtarının adedi)

A:4134312345C:10011234B:12345

Döngü 2, j = 2: A[2] = 1 → C[1]++ = 1. (C[i] = i anahtarının adedi)

A:4134312345C:10111234B:12345

Döngü 2, j = 3: A[3] = 3 → C[3]++ = 1. (C[i] = i anahtarının adedi)

A:4134312345C:10121234B:12345

Döngü 2, j = 4: A[4] = 4 → C[4]++ = 2. (C[i] = i anahtarının adedi)

A:4134312345C:10221234B:12345

Döngü 2, j = 5: A[5] = 3 → C[3]++ = 2. (C[i] = i anahtarının adedi)

A:4134312345C:11221234B:12345

Döngü 3, i = 2: C[2] = C[2] + C[1] = 1. (C[i] = anahtarı ≤ i olanların adedi)

A:4134312345C:11321234B:12345

Döngü 3, i = 3: C[3] = C[3] + C[2] = 3. (C[i] = anahtarı ≤ i olanların adedi)

A:4134312345C:11351234B:12345

Döngü 3, i = 4: C[4] = C[4] + C[3] = 5. (C[i] = anahtarı ≤ i olanların adedi)

A:4134312345C:11351234B:12345

Önek toplamı hazır: C = [1, 1, 3, 5]. C[i], i anahtarlı son elemanın B'deki konumudur.

A:4134312345C:11251234B:312345

Döngü 4, j = 5: A[5] = 3 → B[C[3] = 3] = 3; C[3]−− = 2.

A:4134312345C:11241234B:3412345

Döngü 4, j = 4: A[4] = 4 → B[C[4] = 5] = 4; C[4]−− = 4.

A:4134312345C:11141234B:33412345

Döngü 4, j = 3: A[3] = 3 → B[C[3] = 2] = 3; C[3]−− = 1.

A:4134312345C:01141234B:133412345

Döngü 4, j = 2: A[2] = 1 → B[C[1] = 1] = 1; C[1]−− = 0.

A:4134312345C:01131234B:1334412345

Döngü 4, j = 1: A[1] = 4 → B[C[4] = 4] = 4; C[4]−− = 3.

A:4134312345C:01131234B:1334412345

Sonuç B = [1, 3, 3, 4, 4]. Hiç karşılaştırma yapılmadı; sondan başa gezildiği için eşit anahtarların sırası korunur (kararlı).

Doğrusal Zamanlı Sıralama

Saymalı Sıralama: Karmaşıklık ve Java

DöngüİşSüre
1C[1..k] = 0Θ(k)
2saymaΘ(n)
3önek toplamıΘ(k)
4B'ye yerleştirΘ(n)
ToplamΘ(n + k)
int[] saymaliSirala(int[] dizi) {
  int maks = enBuyuk(dizi);
  int[] sayac = new int[maks + 1];
  for (int x : dizi) sayac[x]++;
  for (int i = 1; i <= maks; i++) sayac[i] += sayac[i - 1];
  int[] cikti = new int[dizi.length];
  for (int i = dizi.length - 1; i >= 0; i--) {
    cikti[sayac[dizi[i]] - 1] = dizi[i];
    sayac[dizi[i]]--;
  }
  return cikti;
}
  • k = O(n) ise Θ(n): Ω(n log n) sınırını aşar, çünkü karşılaştırma yapmaz.
  • Ek bellek Θ(n + k); k çok büyükse (ör. 32 bitlik tamsayılar) pratik değildir. Java sürümü 0-tabanlıdır ve 0 … maks aralığını kullanır.
  • Son döngünün sondan başa gezmesi kararlılığı sağlar → basamak sıralamanın temeli.

Doğrusal Zamanlı Sıralama

Basamak Sıralama (Radix Sort)

  • Tamsayıları basamak basamak sıralar; en anlamsız basamaktan (birler) başlar: LSD.
  • Her geçişte o basamağa göre kararlı bir sıralama (saymalı, k = 10) yapılır.
  • Kararlılık şarttır: onlar basamağına göre sıralarken birler sırası korunmalıdır.
  • d basamak, taban b: Θ(d · (n + b)). d sabitse Θ(n).
  • Ek bellek Θ(n + b); yerinde değildir.
int[] basamakSirala(int[] dizi) {
  int maks = enBuyuk(dizi);
  for (int us = 1; maks / us > 0; us *= 10)
    dizi = basamagaGoreSay(dizi, us);
  return dizi;
}
int[] basamagaGoreSay(int[] dizi, int us) {
  int n = dizi.length;
  int[] cikti = new int[n], sayac = new int[10];
  for (int x : dizi) sayac[(x / us) % 10]++;
  for (int i = 1; i < 10; i++) sayac[i] += sayac[i - 1];
  for (int i = n - 1; i >= 0; i--) {
    int b = (dizi[i] / us) % 10;
    cikti[--sayac[b]] = dizi[i];
  }
  return cikti;
}

Doğrusal Zamanlı Sıralama · Adım adım

Basamak Sıralama Adım Adım

Girdi17045759080224266

Girdi [170, 45, 75, 90, 802, 24, 2, 66]. En büyük sayı 802: 3 basamak → 3 geçiş (en anlamsız basamaktan başlayarak, LSD).

us = 1: birler basamağı1700455755900802224422666

Geçiş 1: her sayının birler basamağı (altta) anahtar olarak kullanılır; eksik basamak 0 sayılır.

birler basamağına göre sıralı1700900802222244455755666

Kararlı saymalı sıralama sonrası: [170, 90, 802, 2, 24, 45, 75, 66]. Eşit basamaklılar önceki sıralarını korudu.

us = 10: onlar basamağı1707909802020242454757666

Geçiş 2: her sayının onlar basamağı (altta) anahtar olarak kullanılır; eksik basamak 0 sayılır.

onlar basamağına göre sıralı8020202424546661707757909

Kararlı saymalı sıralama sonrası: [802, 2, 24, 45, 66, 170, 75, 90]. Eşit basamaklılar önceki sıralarını korudu.

us = 100: yüzler basamağı8028202404506601701750900

Geçiş 3: her sayının yüzler basamağı (altta) anahtar olarak kullanılır; eksik basamak 0 sayılır.

yüzler basamağına göre sıralı2024045066075090017018028

Kararlı saymalı sıralama sonrası: [2, 24, 45, 66, 75, 90, 170, 802]. Tüm basamaklar işlendi → sıralı.

Doğrusal Zamanlı Sıralama

Kova Sıralama (Bucket Sort)

  • Girdi [0, 1) aralığına düzgün dağılmış sayılar olsun.
  • n kova açılır; x değeri ⌊n · x⌋ numaralı kovaya atılır.
  • Her kova (eklemeli sıralamayla) sıralanır, kovalar sırayla birleştirilir.
  • Beklenen süre Θ(n); tüm elemanlar tek kovaya düşerse en kötü Θ(n²).
  • Simülatördeki onuncu algoritmadır; dağılım hakkında varsayım yapar.
A = .78, .17, .39, .26, .72, .94, .21, .12, .23, .680∅1.12.172.21.23.263.394∅5∅6.687.72.788∅9.94Birleştir: .12, .17, .21, .23, .26, .39, .68, .72, .78, .94

Timsort

Timsort: Hibrit Sıralama

  • Tim Peters (2002, Python). Java'da nesne dizileri (Arrays.sort(Object[]), List.sort) ve Python'da sorted Timsort kullanır.
  • Gerçek veride sık görülen sıralı parçaları (run) kullanır: kısa run'lar eklemeli sıralamayla uzatılır, run'lar birleştirmeli sıralamayla birleştirilir.
  • Kararlı; en kötü O(n log n), sıralı girdide Θ(n); O(n) ek bellek.
static final int MIN_PARCA = 4;
void timSirala(int[] dizi) {
  int n = dizi.length;
  for (int i = 0; i < n; i += MIN_PARCA)            // 1) run'lar
    eklemeliSirala(dizi, i, Math.min(i + MIN_PARCA - 1, n - 1));
  for (int boyut = MIN_PARCA; boyut < n; boyut *= 2)  // 2) birleştir
    for (int sol = 0; sol < n; sol += 2 * boyut) {
      int orta = sol + boyut - 1;
      int sag = Math.min(sol + 2 * boyut - 1, n - 1);
      if (orta < sag) birlestir(dizi, sol, orta, sag);
    }
}

Buradaki sürüm sabit uzunluklu run'larla basitleştirilmiştir (gerçek Timsort'ta minrun 32–64, doğal run tespiti ve "galloping" vardır).

Timsort · Adım adım

Timsort Adım Adım (MIN_PARCA = 4)

Girdi, MIN_PARCA = 45021172233194105361278819

Dizi [5, 21, 7, 23, 19, 10, 3, 12, 8, 1], n = 10. Dizi 4'erli parçalara (run) ayrılır (renkler).

eklemeliSirala(0, 3)5071212233194105361278819

Run [0..3] eklemeli sıralama ile sıralandı: [5, 7, 21, 23].

eklemeliSirala(4, 7)5071212233341051261978819

Run [4..7] eklemeli sıralama ile sıralandı: [3, 10, 12, 19].

eklemeliSirala(8, 9)5071212233341051261971889

Run [8..9] eklemeli sıralama ile sıralandı: [1, 8].

boyut = 4: birlestir(0, 3, 7)3051721031241952162371889

boyut = 4: [5, 7, 21, 23] + [3, 10, 12, 19] birleştirildi → [3, 5, 7, 10, 12, 19, 21, 23].

boyut = 4: [8..9] tek başına3051721031241952162371889

boyut = 4: [8..9] parçasının birleşeceği eşi yok (orta = 11 ≥ sag = 9) → aynen kalır.

boyut = 8: birlestir(0, 7, 9)1031527384105126197218239

boyut = 8: [3, 5, 7, 10, 12, 19, 21, 23] + [1, 8] birleştirildi → [1, 3, 5, 7, 8, 10, 12, 19, 21, 23]. Dizi sıralandı.

Karşılaştırma

Sıralama Algoritmalarının Karşılaştırılması

AlgoritmaEn iyiOrtalamaEn kötüEk bellekKararlıYerinde
Kabarcık (bayraklı)Θ(n)Θ(n²)Θ(n²)O(1)EvetEvet
EklemeliΘ(n)Θ(n²)Θ(n²)O(1)EvetEvet
SeçmeliΘ(n²)Θ(n²)Θ(n²)O(1)HayırEvet
Kabuk (n/2 aralık)Θ(n log n)aralığa bağlıΘ(n²)O(1)HayırEvet
BirleştirmeliΘ(n log n)Θ(n log n)Θ(n log n)Θ(n)EvetHayır
HızlıΘ(n log n)Θ(n log n)Θ(n²)O(log n)*HayırEvet
YığınO(n log n)Θ(n log n)Θ(n log n)O(1)HayırEvet
SaymalıΘ(n + k)Θ(n + k)Θ(n + k)Θ(n + k)EvetHayır
Basamak (LSD)Θ(d(n + b))Θ(d(n + b))Θ(d(n + b))Θ(n + b)EvetHayır
KovaΘ(n)Θ(n)†Θ(n²)Θ(n)EvetHayır
TimsortΘ(n)Θ(n log n)Θ(n log n)O(n)EvetHayır

* özyineleme yığını (küçük parçaya önce inilirse). † düzgün dağılımda beklenen. k: anahtar aralığı, d: basamak sayısı, b: taban. Timsort'un Θ(n) en iyi durumu doğal run tespitiyle gerçek sürüm içindir.

Karşılaştırma

Kaç Karşılaştırma? n = 1000

AlgoritmaRastgeleSıralıTers sıralı
Kabarcık (bayraklı)497.960999499.500
Eklemeli252.205999499.500
Seçmeli499.500499.500499.500
Kabuk (n/2)14.7238.00611.716
Birleştirmeli8.6935.0444.932
Hızlı (son eleman pivot)11.384499.500499.500
Yığın16.79117.58315.965
  • Eleman karşılaştırma sayıları; bu bölümdeki kodlar n = 1000 için çalıştırılarak sayıldı (rastgele dizi sabit tohumla üretildi).
  • Karşılaştırma için: n² / 2 ≈ 500.000, n log₂ n ≈ 9.966. Sıralı girdide son eleman pivotlu hızlı sıralama en kötü durumuna düşer.

Karşılaştırma

Hangi Durumda Hangi Algoritma?

Küçük ya da neredeyse sıralıEklemeli sıralama: az ek yük, uyarlanabilir, kararlı.
Genel amaçlı, hızHızlı sıralama (rastgele / üçün ortancası pivot); önbellek dostu, yerinde.
Kararlılık gerekliBirleştirmeli sıralama ya da Timsort (kütüphanelerin nesne sıralaması).
En kötü durum garantisi, az bellekYığın sıralama: O(n log n) ve O(1) ek bellek (introsort'un yedeği).
Küçük tamsayı anahtarlarSaymalı ya da basamak sıralama: Θ(n + k), Θ(d(n + b)).
Bağlı liste, dış bellekBirleştirmeli sıralama: rastgele erişim gerektirmez; disk üzerindeki büyük dosyalar parça parça birleştirilir.

Kabarcık ve seçmeli sıralama öğretim amaçlıdır; seçmeli yalnızca yazmanın çok pahalı olduğu durumlarda anlamlıdır.

Özet

Özet

KonuHatırlanacaklar
Ölçütlerzaman (en iyi/ortalama/en kötü), ek bellek, kararlılık, yerinde, uyarlanabilirlik
Kabarcıkkomşu takas; tur sonunda en büyük sonda; bayrakla en iyi Θ(n), aksi Θ(n²); kararlı
Eklemelianahtarı sakla, büyükleri kaydır, yerleştir; Θ(n + ters çift); küçük/neredeyse sıralı veride en iyi
Seçmelien küçüğü bul, başa al; her zaman n(n − 1)/2 karşılaştırma, ≤ n − 1 takas; kararsız
Kabukazalan aralıklarla eklemeli sıralama; yerinde, kararsız
Birleştirmeliböl–sırala–birleştir; T(n) = 2T(n/2) + Θ(n) = Θ(n log n); Θ(n) ek bellek; kararlı
Hızlıpivot etrafında parçala; ortalama Θ(n log n), en kötü Θ(n²); yerinde, kararsız
YığınO(n) max-heap kur, n − 1 kez kökü sona al ve süz; O(n log n), O(1) ek bellek
Doğrusalkarşılaştırmalı alt sınır Ω(n log n); saymalı Θ(n + k), basamak Θ(d(n + b)), kova beklenen Θ(n)

Özet

Etkileşimli Simülatörler

Sıralama AlgoritmalarıOn algoritmayı (kabarcık, eklemeli, seçmeli, birleştirmeli, hızlı, saymalı, basamak, kova, yığın, kabuk) çubuk grafik üzerinde adım adım çalıştırın; karşılaştırılan ve sıralanan elemanları ve işlem günlüğünü izleyin, karmaşıklık tablosuna bakın.
Sıralama YarışıKabarcık, eklemeli, seçmeli ve hızlı sıralamayı aynı rastgele dizi (8–40 eleman) üzerinde yan yana yarıştırın; karşılaştırma ve yer değiştirme sayılarını karşılaştırın.
Sıralama Özellikleri LaboratuvarıEşit anahtarlı kayıtları (3, A), (1, B), (3, C) … eklemeli ya da seçmeli sıralamayla sıralayın; göreli sıranın korunup korunmadığını (kararlılık) görün.

Özet

Sık Yapılan Hatalar

Dizi sınırını aşmakKabarcıkta iç döngü j < n − 1 − i olmalı; j < n yazmak dizi[j+1] ile taşar.
Anahtarı saklamamakEklemeli sıralamada gecici önceden alınmazsa ilk kaydırma onu ezer.
En küçüğü değer olarak tutmakSeçmeli sıralamada indis tutulmazsa yer değiştirme yapılamaz.
Kararlılığı bozmakBirleştirmede <= yerine <, saymalıda baştan sona gezmek eşit anahtarların sırasını bozar.
Pivotu özyinelemeye katmakhizliSirala(dizi, alt, p) yazmak pivotu tekrar işler; iki eleman kalınca sonsuz özyineleme olabilir.
"Quicksort her zaman n log n"Sıralı girdide sabit pivot Θ(n²) ve n derinlikli özyineleme (StackOverflowError) verir.

Özet

Örnek Problemler

  1. [5, 2, 4, 6, 1, 3] dizisine bayraklı kabarcık sıralama uygulanıyor. Her tur sonundaki diziyi yazın.
  2. Aynı diziyi eklemeli sıralama kaç karşılaştırma ve kaç kaydırma ile sıralar? Seçmeli sıralama kaç yer değiştirme yapar?
  3. parcala (Lomuto, pivot = son eleman) [2, 8, 7, 1, 3, 5, 6, 4] üzerinde çalışınca dizi ve dönüş değeri ne olur?
  4. [4, 10, 3, 5, 1] dizisinden aşağıdan yukarı kurulan max-heap nedir?
  5. A = [2, 5, 3, 0, 2, 3, 0, 3] (anahtarlar 0 … 5) için saymalı sıralamanın 3. döngüden sonraki C dizisi nedir?
  6. Birleştirmeli sıralama 8 elemanı en fazla kaç karşılaştırmayla sıralar?
Cevapları göster
  1. [2, 4, 5, 1, 3, 6] → [2, 4, 1, 3, 5, 6] → [2, 1, 3, 4, 5, 6] → [1, 2, 3, 4, 5, 6] → [1, 2, 3, 4, 5, 6] (son turda takas yok → durur).
  2. Eklemeli: 12 karşılaştırma, 9 kaydırma (= ters çift sayısı). Seçmeli: 15 karşılaştırma, 3 yer değiştirme.
  3. [2, 1, 3, 4, 7, 5, 6, 8], dönüş 3 (pivot 4 indis 3'te).
  4. [10, 5, 3, 4, 1]: önce i = 1 (10 zaten büyük), sonra i = 0: 4 ↔ 10, 4 ↔ 5.
  5. C = [2, 2, 4, 7, 7, 8] (adetler [2, 0, 2, 3, 0, 1] ve önek toplamları).
  6. Her düzeyde birleştirilen m eleman en fazla m − 1 karşılaştırma ister: 4·1 + 2·3 + 1·7 = 17.

Özet

Alıştırmalar

  1. n = 6 elemanlı ters sıralı dizide kabarcık sıralama kaç karşılaştırma ve kaç yer değiştirme yapar?
  2. Seçmeli sıralamanın kararsız olduğunu gösteren üç elemanlı bir örnek verin.
  3. Eklemeli sıralamada doğru konumu ikili arama ile bulursak zaman karmaşıklığı ne olur?
  4. Hızlı sıralamayı (son eleman pivot) zaten sıralı 1000 elemanlı diziyle çağırınca ne olur? Nasıl düzeltilir?
  5. [329, 457, 657, 839, 436, 720, 355] dizisini LSD basamak sıralama ile sıralayın; her geçişten sonraki diziyi yazın.
  6. Bir dizideki ters çift sayısını O(n log n)'de bulan bir yöntem önerin.
Cevaplar / ipuçları
  1. Her tur tüm çiftler ters: 5 + 4 + 3 + 2 + 1 = 15 karşılaştırma ve 15 yer değiştirme.
  2. [2ₐ, 2ᵦ, 1] → ilk turda 1 ile 2ₐ yer değiştirir → [1, 2ᵦ, 2ₐ].
  3. Karşılaştırmalar O(n log n)'e iner ama kaydırmalar hâlâ Θ(n²) → toplam yine Θ(n²).
  4. Her parçalama yalnızca pivotu ayırır: 999 + 998 + … + 1 = 499.500 karşılaştırma, 1000 derinlikli özyineleme. Rastgele pivot ya da üçün ortancası.
  5. Birler: [720, 355, 436, 457, 657, 329, 839]; onlar: [720, 329, 436, 839, 355, 457, 657]; yüzler: [329, 355, 436, 457, 657, 720, 839].
  6. Birleştirmeli sıralamayı değiştirin: sağdan bir eleman alındığında sol yarıda kalan eleman sayısı (L.length − i) kadar ters çift eklenir; toplam O(n log n).

Özet

Kaynaklar

  • Cormen, Leiserson, Rivest ve Stein, Introduction to Algorithms, 4. baskı, MIT Press, 2022 (Bölüm 2, 6, 7, 8).
  • Sedgewick ve Wayne, Algorithms, 4. baskı, Addison-Wesley, 2011 (Bölüm 2: Sorting).
  • D. E. Knuth, The Art of Computer Programming, Vol. 3: Sorting and Searching, 2. baskı, 1998.
  • E. D. Demaine ve C. E. Leiserson, MIT 6.046J Introduction to Algorithms ders notları, 2005 (parçalama ve saymalı sıralama örnekleri).
  • C. A. R. Hoare, "Quicksort", The Computer Journal 5(1), 1962; D. L. Shell, "A High-Speed Sorting Procedure", CACM 2(7), 1959.
  • T. Peters, "listsort.txt" (Timsort tasarım notu), CPython, 2002.

Son

Bölüm 2: Sıralama Algoritmaları
Sonraki bölüm: Bölüm 3: Arama Algoritmaları
1 / 1 Sercan KÜLCÜ, Tüm hakları saklıdır.