Bölüm 10: Diziler

Bilgisayar ve Programlamaya Giriş
TanımİndisDöngüAramaMatris
Sercan KÜLCÜ · Giresun Üniversitesi

Giriş

Öğrenme Çıktıları

Oluşturma

Dizi bildirmek ve ilk değer vermek.

Erişim

İndis ve length kullanmak.

İşleme

Diziyi döngülerle gezmek ve dönüştürmek.

Matris

İki boyutlu dizilerle satır-sütun işlemleri yapmak.

Temeller

Dizi Nedir?

  • Aynı tipte, sabit sayıda öğeyi tek nesnede ardışık hücrelerde saklar.
  • Öğelere sıfır tabanlı indisle erişilir: sayilar[0] … sayilar[4].
  • Uzunluk (length) oluşturulduktan sonra değişmez.
  • Dizi değişkeni öğeleri değil, heap'teki dizi nesnesinin referansını (adresini) tutar.
YığınHeapsayilar0010203040length = 5 (sabit)aynı tip: hepsi int

Değişken → dizi nesnesi (referans oku)

Temeller

Dizi ve İndis

010120230340450aa.length = 5ilk: a[0]son: a[a.length − 1] = a[4]a[2] → 30
  • İlk indis 0, son indis length − 1'dir (5 öğe → 0…4).
  • a[i] adresi doğrudan hesaplanır (başlangıç + i × hücre boyu); bu yüzden erişim diziyi gezmeden, sabit sürede (O(1)) olur.

Temeller

Avantaj ve Sınır

AvantajSınır
İndisle hızlı erişimBoyut sabittir
Öğe tipi tutarlıdırAraya ekleme maliyetlidir
Döngüyle kolay işlenirSınır aşımı çalışma zamanı hatasıdır
Bellekte düzenli yapıTek bir öğe tipi tutar
İndisle erişim: doğrudan atlama100201302403504adres = başlangıç + 3 × hücre boyua[3] → 40: tek adım, O(1)Araya ekleme: 15 → indis 1102030401015203040sağdaki 3 öğebirer kayarDizi doluysa: yeni, daha büyük dizi + kopyalama (boyut sabit)

Bildirim

Dizi Oluşturma

int[] sayilar = new int[5];
String[] adlar = {"Ada", "Can", "Ece"};
double[] olcumler;
olcumler = new double[10];
  • new ile oluşturulan dizinin hücreleri tipin varsayılan değerini alır (sağda).
  • İlklendirici {…} kullanılınca uzunluk değer sayısından çıkarılır (adlar.length = 3).
int[] a = new int[3];000double[] d = new double[3];0.00.00.0boolean[] b = new boolean[3];falsefalsefalseString[] s = new String[3];nullnullnull

Varsayılan başlangıç değerleri

Bildirim · Kodu adım adım çalıştır

Kod İzleme: Dizi Oluşturma

Yığın (değişkenler)Heap (nesneler)sayilar?

Bildirim: yığında yalnızca sayilar adlı referans değişkeni açılır; henüz bir dizi yok.

Yığın (değişkenler)Heap (nesneler)00102030length = 4sayilar

new int[4] heap'te 4 hücreli dizi oluşturur, hepsi 0. Değişkene dizinin referansı yazılır (ok).

Yığın (değişkenler)Heap (nesneler)07102030length = 4sayilar

sayilar[0] = 7: ok izlenir, 0 numaralı hücreye 7 yazılır.

Yığın (değişkenler)Heap (nesneler)07102032length = 4sayilar

sayilar[3] = 2: son hücre (indis length − 1 = 3) güncellenir.

Yığın (değişkenler)Heap (nesneler)07102032length = 40Ada1Can2Ecelength = 3sayilaradlar

İlklendirici {…}: 3 değer var → uzunluk 3 olan dizi kurulur ve adlar onu gösterir.

Yığın (değişkenler)Heap (nesneler)07102032length = 40Ada1Can2Ecelength = 3sayilaradlar

length bir alandır (parantez yok): 4 ve 3 yazılır.

int[] sayilar;
sayilar = new int[4];
sayilar[0] = 7;
sayilar[3] = 2;
String[] adlar = {"Ada", "Can", "Ece"};
System.out.println(sayilar.length + " "
                   + adlar.length);

Erişim · Kodu adım adım çalıştır

Öğe Okuma ve Yazma

Yığın (değişkenler)Heap (nesneler)070185290length = 3puanlar

Üç öğeli dizi oluşur; indisler 0, 1, 2.

Yığın (değişkenler)Heap (nesneler)070185290length = 3puanlarilk70

Okuma: puanlar[0] ilk hücredeki değeri verir → ilk = 70.

Yığın (değişkenler)Heap (nesneler)070188290length = 3puanlarilk70

Yazma: atamanın solundaki puanlar[1] hücrenin kendisidir; 85 silinir, 88 yazılır.

Yığın (değişkenler)Heap (nesneler)070188290length = 3puanlarilk70son90

puanlar.length - 1 = 3 − 1 = 2 → son öğe 90. Dizi boyu değişse de kod doğru kalır.

Yığın (değişkenler)Heap (nesneler)070188290length = 3puanlarilk70son90

İki değer aralarında boşlukla yazdırılır.

int[] puanlar = {70, 85, 90};
int ilk = puanlar[0];
puanlar[1] = 88;
int son = puanlar[puanlar.length - 1];
System.out.println(ilk + " " + son);

Erişim

Sınır Dışı Hatası

0418263143-1✗5✗geçerli: 0 … length − 1 = 4a[-1]a[5]a.length = 5 ama a[5] YOK → ArrayIndexOutOfBoundsException
  • Geçerli indisler 0 ile length − 1 arasındadır; negatif indis ve length'in kendisi geçersizdir.
  • Derleyici bunu yakalamaz; program çalışırken ArrayIndexOutOfBoundsException ile durur.
Döngü koşulu i < dizi.length olmalıdır; <= bir tur fazla döner.

Erişim · Kodu adım adım çalıştır

Kod İzleme: Bir Tur Fazla (<=)

0418263yoka

Uzunluğu 3 olan dizi: geçerli indisler 0, 1, 2.

0418263yoka▲ i

0 <= 3 → true, gövdeye girilir.

0418263yoka▲ i

a[0] = 4 yazdırılır.

0418263yoka▲ i

i++ → 1 <= 3 → true, gövdeye girilir.

0418263yoka▲ i

a[1] = 8 yazdırılır.

0418263yoka▲ i

i++ → 2 <= 3 → true, gövdeye girilir.

0418263yoka▲ i

a[2] = 6 yazdırılır.

0418263yoka▲ i

i++ → 3 <= 3 → true — dikkat: 3 geçersiz indis ama koşul yine de doğru!

0418263yoka▲ i

a[3]: böyle bir hücre yok → program hata ile durur. Çözüm: koşulu i < a.length yapmak.

int[] a = {4, 8, 6};
for (int i = 0; i <= a.length; i++) {
    System.out.println(a[i]);
}

Döngüler · Kodu adım adım çalıştır

Klasik for ile Gezinme

070188290puanlar

Dizi hazır; i indis olarak 0'dan başlayacak.

070188290▲ ipuanlar

int i = 0; 0 < 3 → true

070188290▲ ipuanlar

puanlar[0] = 70; %d: %d kalıbı 0: 70 üretir.

070188290▲ ipuanlar

i++ → 1 < 3 → true

070188290▲ ipuanlar

puanlar[1] = 88; %d: %d kalıbı 1: 88 üretir.

070188290▲ ipuanlar

i++ → 2 < 3 → true

070188290▲ ipuanlar

puanlar[2] = 90; %d: %d kalıbı 2: 90 üretir.

070188290puanlari = 3

i++ → 3 < 3 → false → döngü biter; i = length olduğu için a[i]'ye hiç erişilmez.

int[] puanlar = {70, 88, 90};
for (int i = 0; i < puanlar.length; i++) {
  System.out.printf("%d: %d%n", i, puanlar[i]);
}

İndis gerektiğinde (konum yazdırmak, komşu öğeye bakmak, hücreye yazmak) klasik for kullanılır.

Döngüler · Kodu adım adım çalıştır

Gelişmiş for (for-each)

070188290puanlar

Gelişmiş for dizinin öğelerini sırayla verir; indis yoktur.

070188290puanlarpuan70kopya

1. tur: puan'a puanlar[0]'ın kopyası (70) konur.

070188290puanlarpuan75kopya

puan = 75 olur; dizideki hücre 70 olarak kalır — değişen yalnızca kopya.

070188290puanlarpuan75kopya

75 yazdırılır.

070188290puanlarpuan88kopya

2. tur: puan'a puanlar[1]'in kopyası (88) konur.

070188290puanlarpuan93kopya

puan = 93 olur; dizideki hücre 88 olarak kalır — değişen yalnızca kopya.

070188290puanlarpuan93kopya

93 yazdırılır.

070188290puanlarpuan90kopya

3. tur: puan'a puanlar[2]'nin kopyası (90) konur.

070188290puanlarpuan95kopya

puan = 95 olur; dizideki hücre 90 olarak kalır — değişen yalnızca kopya.

070188290puanlarpuan95kopya

95 yazdırılır.

070188290puanlar

Öğe kalmadı → döngü biter; puan değişkeni kapsam dışına çıkar.

070188290puanlar

puanlar[0] hâlâ 70: gelişmiş for'da döngü değişkenine atama diziyi değiştirmez.

int[] puanlar = {70, 88, 90};
for (int puan : puanlar) {
    puan = puan + 5;
    System.out.println(puan);
}
System.out.println(puanlar[0]);

İşlemler · Kodu adım adım çalıştır

Toplam ve Ortalama

04172236sayilar

Dört öğeli dizi.

04172236sayilartoplam0

Biriktirici toplam = 0 ile başlar.

04172236sayilartoplam4

deger = 4 → toplam += deger: 0 + 4 = 4.

04172236sayilartoplam11

deger = 7 → toplam += deger: 4 + 7 = 11.

04172236sayilartoplam13

deger = 2 → toplam += deger: 11 + 2 = 13.

04172236sayilartoplam19

deger = 6 → toplam += deger: 13 + 6 = 19.

04172236sayilartoplam19

Döngü bitti. ortalama 0 ile başlatılır (boş dizi için güvenli değer).

04172236sayilartoplam19

4 > 0 → true: dizi boş değil, bölme yapılabilir.

04172236sayilartoplam19

(double) 19 / 4 = 4.75. Dönüşüm olmasa tam sayı bölmesi 4 verirdi.

04172236sayilartoplam19

Sonuçlar yazdırılır.

int[] sayilar = {4, 7, 2, 6};
int toplam = 0;
for (int deger : sayilar) toplam += deger;
double ortalama = 0;
if (sayilar.length > 0)
    ortalama = (double) toplam / sayilar.length;
System.out.println(toplam + " " + ortalama);

İşlemler · Kodu adım adım çalıştır

En Küçük ve En Büyük

05132931sayilar

Dizi: 5, 3, 9, 1.

05132931▲ minmaxsayilar

İlk öğe hem min hem max adayıdır (0 ile başlatmak negatif/pozitif dizilerde yanlış sonuç verirdi).

05132931▲ minmaxsayilar

1. tur: deger = 5.

05132931▲ minmaxsayilar

5 < 5 → false; min değişmez.

05132931▲ minmaxsayilar

5 > 5 → false; max değişmez.

05132931▲ minmaxsayilar

2. tur: deger = 3.

05132931▲ min▲ maxsayilar

3 < 5 → true: min = 3.

05132931▲ min▲ maxsayilar

3 > 5 → false; max değişmez.

05132931▲ min▲ maxsayilar

3. tur: deger = 9.

05132931▲ min▲ maxsayilar

9 < 3 → false; min değişmez.

05132931▲ min▲ maxsayilar

9 > 5 → true: max = 9.

05132931▲ min▲ maxsayilar

4. tur: deger = 1.

05132931▲ min▲ maxsayilar

1 < 3 → true: min = 1.

05132931▲ min▲ maxsayilar

1 > 9 → false; max değişmez.

05132931▲ min▲ maxsayilar

Tüm öğelere bakıldı (n = 4 tur) → 1 9.

int[] sayilar = {5, 3, 9, 1};
int min = sayilar[0], max = sayilar[0];
for (int deger : sayilar) {
    if (deger < min) min = deger;
    if (deger > max) max = deger;
}
System.out.println(min + " " + max);

Boş dizide sayilar[0] hata verir; gerçek kodda önce sayilar.length == 0 durumu ele alınmalıdır.

İşlemler · Kodu adım adım çalıştır

Diziyi Ters Çevirme (iki işaretçi)

0112233445dizi

Tersine çevrilecek dizi.

0112233445▲ sol▲ sagdizi

İki işaretçi: sol = 0 ve sag = length − 1 = 4.

0112233445▲ sol▲ sagdizi

0 < 4 → true, uçlar yer değiştirecek.

0112233445▲ sol▲ sagdizigecici1

gecici = dizi[0] = 1: soldaki değer kaybolmasın diye saklanır.

0512233445▲ sol▲ sagdizigecici1

dizi[0] = dizi[4] → sol hücreye 5 yazılır.

0512233441▲ sol▲ sagdizigecici1

dizi[4] = gecici → sağ hücreye 1. Takas tamam.

0512233441▲ sol▲ sagdizi

İşaretçiler merkeze yaklaşır: sol = 1, sag = 3.

0512233441▲ sol▲ sagdizi

1 < 3 → true, uçlar yer değiştirecek.

0512233441▲ sol▲ sagdizigecici2

gecici = dizi[1] = 2: soldaki değer kaybolmasın diye saklanır.

0514233441▲ sol▲ sagdizigecici2

dizi[1] = dizi[3] → sol hücreye 4 yazılır.

0514233241▲ sol▲ sagdizigecici2

dizi[3] = gecici → sağ hücreye 2. Takas tamam.

0514233241▲ solsagdizi

İşaretçiler merkeze yaklaşır: sol = 2, sag = 2.

0514233241▲ solsagdizi

2 < 2 → false: işaretçiler ortada buluştu → dizi ters çevrildi.

int[] dizi = {1, 2, 3, 4, 5};
int sol = 0, sag = dizi.length - 1;
while (sol < sag) {
    int gecici = dizi[sol];
    dizi[sol] = dizi[sag];
    dizi[sag] = gecici;
    sol++;
    sag--;
}

n/2 takas yapılır; ek dizi gerekmez (yerinde, O(1) ek alan).

İşlemler · Kodu adım adım çalıştır

Ortalamanın Üstündekileri Sayma

060175290345480notlar

Beş öğrencinin notu. Önce ortalama, sonra ortalamanın üstündekiler: iki geçiş gerekir.

060175290345480notlar

1. geçiş: toplam biriktirilir.

060175290345480notlar

x = 60 → toplam = 60.

060175290345480notlar

x = 75 → toplam = 135.

060175290345480notlar

x = 90 → toplam = 225.

060175290345480notlar

x = 45 → toplam = 270.

060175290345480notlar

x = 80 → toplam = 350.

060175290345480notlarort70.0

(double) 350 / 5 = 70.0.

060175290345480notlarort70.0

2. geçiş için sayaç: ustte = 0.

060175290345480notlarort70.0

60 > 70.0 → false.

060175290345480notlarort70.0✓

75 > 70.0 → true: ustte = 1.

060175290345480notlarort70.0✓✓

90 > 70.0 → true: ustte = 2.

060175290345480notlarort70.0✓✓

45 > 70.0 → false.

060175290345480notlarort70.0✓✓✓

80 > 70.0 → true: ustte = 3.

060175290345480notlarort70.0✓✓✓

Ortalama 70.0, üstünde 3 not var.

int[] notlar = {60, 75, 90, 45, 80};
int toplam = 0;
for (int x : notlar) toplam += x;
double ort = (double) toplam / notlar.length;
int ustte = 0;
for (int x : notlar)
  if (x > ort) ustte++;
System.out.println(ort + " " + ustte);

İşlemler · Kodu adım adım çalıştır

Dizideki En Büyük İkinci Öğe

071122531249aenBuyukMINikinciMIN

İki aday en küçük int değeriyle (Integer.MIN_VALUE) başlar; her öğe bir kez incelenir.

071122531249aenBuyuk7ikinciMIN

7 > MIN → yeni en büyük: eski en büyük (MIN) ikinciye iner, enBuyuk = 7.

071122531249aenBuyuk12ikinci7

12 > 7 → yeni en büyük: eski en büyük (7) ikinciye iner, enBuyuk = 12.

071122531249aenBuyuk12ikinci7

Değişiklik yok: 5 ikinciden (7) büyük değil.

071122531249aenBuyuk12ikinci7

Değişiklik yok: 12 == enBuyuk (tekrar), sayılmaz.

071122531249aenBuyuk12ikinci9

9 en büyükten küçük ama ikinciden büyük ve 9 != 12 → ikinci = 9.

071122531249aenBuyuk12ikinci9

Tek geçişte sonuç: 9 (12 iki kez geçse de ikinci en büyük 9'dur).

int[] a = {7, 12, 5, 12, 9};
int enBuyuk = Integer.MIN_VALUE;
int ikinci = Integer.MIN_VALUE;
for (int x : a) {
  if (x > enBuyuk) {
    ikinci = enBuyuk;
    enBuyuk = x;
  } else if (x > ikinci && x != enBuyuk) {
    ikinci = x;
  }
}
System.out.println(ikinci);

İşlemler · Kodu adım adım çalıştır

Frekans Sayma: Zar Histogramı

atislar36316300102030405060sayac

Atışlar sabit verildi (gerçekte rastgele.nextInt(6) + 1). 7 hücreli sayaç: indis = zar değeri (0 kullanılmaz). Bu, değeri indis olarak kullanma hilesidir.

atislar36316300102031405060sayac

zar = 3 → sayac[3]++ → 1. if-else zincirine gerek yok!

atislar36316300102031405061sayac

zar = 6 → sayac[6]++ → 1. if-else zincirine gerek yok!

atislar36316300102032405061sayac

zar = 3 → sayac[3]++ → 2. if-else zincirine gerek yok!

atislar36316300112032405061sayac

zar = 1 → sayac[1]++ → 1. if-else zincirine gerek yok!

atislar36316300112032405062sayac

zar = 6 → sayac[6]++ → 2. if-else zincirine gerek yok!

atislar36316300112033405062sayac

zar = 3 → sayac[3]++ → 3. if-else zincirine gerek yok!

atislar36316300112033405062sayac

y = 1: sayac[1] = 1 kadar yıldız.

atislar36316300112033405062sayac

y = 2: sayac[2] = 0 kadar yıldız (hiç yok).

atislar36316300112033405062sayac

y = 3: sayac[3] = 3 kadar yıldız.

atislar36316300112033405062sayac

y = 4: sayac[4] = 0 kadar yıldız (hiç yok).

atislar36316300112033405062sayac

y = 5: sayac[5] = 0 kadar yıldız (hiç yok).

atislar36316300112033405062sayac

y = 6: sayac[6] = 2 kadar yıldız.

int[] atislar = {3, 6, 3, 1, 6, 3};
int[] sayac = new int[7];
for (int zar : atislar)
  sayac[zar]++;
for (int y = 1; y <= 6; y++) {
  System.out.print(y + ": ");
  for (int k = 0; k < sayac[y]; k++)
    System.out.print("*");
  System.out.println();
}

İşlemler · Kodu adım adım çalıştır

Eratosthenes Eleği (boolean dizi)

01234567891011121314151617181920asalDegil[i] = true olanlar üstü çizili

Tüm hücreler false: başlangıçta 2…20 hepsi asal adayı.

01234567891011121314151617181920asalDegil[i] = true olanlar üstü çizili

2 × 2 = 4 <= 20 → true.

01234567891011121314151617181920asalDegil[i] = true olanlar üstü çizili

2 elenmemiş → asal. Katları 2·2'den başlayarak işaretlenir: k = 4, 6, 8, 10, 12, 14, 16, 18, 20.

01234567891011121314151617181920asalDegil[i] = true olanlar üstü çizili

3 × 3 = 9 <= 20 → true.

01234567891011121314151617181920asalDegil[i] = true olanlar üstü çizili

3 elenmemiş → asal. Katları 3·3'ten başlayarak işaretlenir: k = 9, 12, 15, 18.

01234567891011121314151617181920asalDegil[i] = true olanlar üstü çizili

4 × 4 = 16 <= 20 → true.

01234567891011121314151617181920asalDegil[i] = true olanlar üstü çizili

asalDegil[4] = true → 4 zaten elenmiş, katlarına bakmaya gerek yok.

01234567891011121314151617181920asalDegil[i] = true olanlar üstü çizili

5 × 5 = 25 <= 20 → false: √20'den büyük bölen aramaya gerek yok.

012✓3✓45✓67✓891011✓1213✓14151617✓1819✓20asalDegil[i] = true olanlar üstü çizili

Elenmemiş olanlar yazdırılır: 8 asal.

int n = 20;
boolean[] asalDegil = new boolean[n + 1];
for (int i = 2; i * i <= n; i++)
  if (!asalDegil[i])
    for (int k = i * i; k <= n; k += i)
      asalDegil[k] = true;
for (int i = 2; i <= n; i++)
  if (!asalDegil[i]) System.out.print(i + " ");

İşlemler

Dizi Kopyalama

  • b = a öğeleri değil referansı kopyalar: iki ok aynı nesneyi gösterir.
  • Bağımsız kopya için a.clone(), Arrays.copyOf(a, a.length) veya System.arraycopy.
  • Nesne dizilerinde bu yöntemler öğe referanslarını kopyalar; nesnelerin kendisi çoğaltılmaz (sığ kopya).
YığınHeapabc011223011223b = a → aynı nesnec = a.clone() → yeni nesne

İşlemler · Kodu adım adım çalıştır

Kod İzleme: Referans Kopyası ve Öğe Kopyası

Yığın (değişkenler)Heap (nesneler)011223a

Heap'te bir dizi; a onu gösterir.

Yığın (değişkenler)Heap (nesneler)011223ab

b = a: yeni dizi oluşmaz; b'ye aynı referans yazılır → iki ok aynı nesnede.

Yığın (değişkenler)Heap (nesneler)0991223ab

b[0] = 99: b'nin gösterdiği nesne değişti — bu, a'nın da nesnesi!

Yığın (değişkenler)Heap (nesneler)0991223ab

a[0] artık 99. Referans kopyası bağımsız bir dizi değildir.

Yığın (değişkenler)Heap (nesneler)09912230991223kopyaabc

a.clone() heap'te yeni bir dizi açar ve öğeleri tek tek kopyalar.

Yığın (değişkenler)Heap (nesneler)099122309915023kopyaabc

c[1] = 50 yalnızca kopyayı değiştirir.

Yığın (değişkenler)Heap (nesneler)099122309915023kopyaabc

a[1] = 2 (değişmedi), c[1] = 50.

int[] a = {1, 2, 3};
int[] b = a;
b[0] = 99;
System.out.println(a[0]);
int[] c = a.clone();
c[1] = 50;
System.out.println(a[1] + " " + c[1]);

İşlemler

Arrays Yardımcıları

import java.util.Arrays;
int[] a = {5, 2, 9}, r = {10, 20, 30, 40, 50}, p = {1, 2, 3}, q = {1, 2, 3}, f = new int[4];
int[][] m = {{1, 2}, {3, 4}};
ÇağrıSonuç
Arrays.toString(a)[5, 2, 9]
Arrays.deepToString(m)[[1, 2], [3, 4]]
Arrays.toString(m)[[I@… (adres)
Arrays.fill(f, 7) → f[7, 7, 7, 7]
p == q / p.equals(q)false / false
Arrays.equals(p, q)true
Kopya (Arrays.)Sonuç
copyOf(a, 5)[5, 2, 9, 0, 0]
copyOf(a, 2)[5, 2]
copyOfRange(r, 1, 4)[20, 30, 40]
  • == ve equals referansı karşılaştırır; içerik için Arrays.equals (2B için deepEquals).
  • copyOf uzunluk büyükse sıfırla doldurur, küçükse keser; copyOfRange'te bitiş indisi dahil değildir.

Arama

Doğrusal Arama: ara(d, 6)

static int ara(int[] dizi, int hedef) {
    for (int i = 0; i < dizi.length; i++)
        if (dizi[i] == hedef) return i;
    return -1;
}
// main içinde:
int[] d = {8, 3, 6, 2};
System.out.println(ara(d, 6));
idizi[i]== 6 ?
08false
13false
26true → return 2
  • Çıktı: 2. İlk eşleşmede döngü erken biter.
  • dizi parametresi d ile aynı diziyi gösterir (referans aktarılır); kopya oluşmaz.
  • Hedef yoksa n karşılaştırmadan sonra −1 döner → O(n).

Arama

Sıralama ve İkili Arama

  • Arrays.sort(a) diziyi küçükten büyüğe yerinde sıralar (özgün sıra kaybolur).
  • Arrays.binarySearch(a, x) yalnızca sıralı dizide doğru çalışır; bulursa indisi döndürür; bulamazsa -(eklenme noktası) - 1 gibi negatif bir değer döndürür.
  • Her adımda aralığı yarıya indirdiği için doğrusal aramadan çok daha az karşılaştırma yapar.
  • İkisi için de import java.util.Arrays; gerekir.
önce52917Arrays.sort(a)sonra (yerinde sıralı)0112253749Arrays.binarySearch(a, 7) → 3

Arama

Ortanca (Medyan)

  • Ortanca: sıralanmış dizinin ortasındaki değer; öğe sayısı çiftse ortadaki ikisinin ortalaması.
  • Uç değerden etkilenmez: {1, 2, 3, 4, 100} için ortalama 22.0, ortanca 3.
  • Arrays.sort diziyi yerinde değiştirir; bu yüzden kopya sıralanır.
int[] a = {7, 3, 9, 1, 5};
int[] s = Arrays.copyOf(a, a.length);
Arrays.sort(s);    // a bozulmaz
int n = s.length;
double m = (n % 2 == 1) ? s[n / 2]
    : (s[n/2 - 1] + s[n/2]) / 2.0;
System.out.println(m);   // 5.0
tek sayıda öğe (n = 5), sıralı0113253749s[n / 2] = s[2] → 5çift sayıda öğe (n = 4), sıralı02132638(s[1] + s[2]) / 2.0 → 4.5

Sıralama

Kabarcık Sıralaması (Bubble Sort)

int[] a = {5, 1, 4, 2};
int n = a.length;
for (int gecis = 0; gecis < n - 1; gecis++) {
  for (int j = 0; j < n - 1 - gecis; j++) {
    if (a[j] > a[j + 1]) {
      int gecici = a[j];
      a[j] = a[j + 1];
      a[j + 1] = gecici;
    }
  }
}
geçişgeçiş sonu dizikarş.takas
1[1, 4, 2, 5]33
2[1, 2, 4, 5]21
3[1, 2, 4, 5]10
  • Her geçişte kalanların en büyüğü sona yerleşir; iç döngü her geçişte bir kısalır.
  • Toplam 3 + 2 + 1 = 6 karşılaştırma → O(n²).
  • 3. geçişte hiç takas yok: dizi 2. geçişten sonra sıralıydı.

Sıralama

Eklemeli Sıralama (Insertion Sort)

int[] a = {4, 3, 5, 1};
for (int i = 1; i < a.length; i++) {
  int anahtar = a[i];
  int j = i - 1;
  while (j >= 0 && a[j] > anahtar) {
    a[j + 1] = a[j];
    j--;
  }
  a[j + 1] = anahtar;
}
ianahtarsağa kayanlartur sonu dizi
134[3, 4, 5, 1]
25—[3, 4, 5, 1]
315, 4, 3[1, 3, 4, 5]
  • Sol bölüm hep sıralıdır; anahtardan büyük öğeler birer sağa kayar, anahtar açılan yere konur.
  • Neredeyse sıralı dizide çok hızlı; en kötü durumda (ters sıralı) O(n²).

Arama

İkili Arama: hedef = 23

int[] a = {2, 5, 8, 12, 16, 23, 38, 56};
int hedef = 23, lo = 0, hi = a.length - 1;
int sonuc = -1;
while (lo <= hi) {
  int mid = (lo + hi) / 2;
  if (a[mid] == hedef) { sonuc = mid; break; }
  if (a[mid] < hedef) lo = mid + 1;
  else hi = mid - 1;
}
System.out.println(sonuc);
turlohimida[mid]karar
10731212 < 23 → lo = 4
247523bulundu: sonuc = 5
  • Çıktı: 5. Dizi sıralı olmalıdır.
  • 2 turda bulundu; doğrusal arama 6 karşılaştırma yapardı → O(log n).

Arama

Başarısız Arama: Arrays.binarySearch(a, 5) → -3

static int ara(int[] a, int x) {
  int lo = 0, hi = a.length - 1;
  while (lo <= hi) {
    int mid = (lo + hi) / 2;
    if (a[mid] == x) return mid;
    if (a[mid] < x) lo = mid + 1; else hi = mid - 1;
  }
  return -(lo + 1);
}
System.out.println(ara(new int[]{2, 4, 6, 8}, 5));
turlohimida[mid]karar
103144 < 5 → lo = 2
223266 > 5 → hi = 1
—21lo > hi: döngü biter
  • Sonuç -(lo + 1) = -3; negatif değer “yok” demektir.
  • Ekleme noktası = -(-3) - 1 = 2: 5 dizide 2 numaralı konuma girerdi. Arrays.binarySearch da aynı değeri döndürür.

Analiz

Temel Karmaşıklıklar

İşlemZaman
İndisle erişimO(1)
Doğrusal aramaO(n)
Sona kadar gezinmeO(n)
Ortaya ekleme / silmeO(n)
İki iç içe tam gezinmeO(n²)
1'e 4 eklemek için sağdakiler kayar:031825364sonra:0314283546kaydırma sayısı ≈ n → O(n)

Matris

İki Boyutlu Dizi

int[][] matris = {
    {1, 2, 3},
    {4, 5, 6}
};
int deger = matris[1][2]; // 6
  • İlk indis satır, ikinci indis sütun.
  • Java'da çok boyutlu dizi, dizilerin dizisidir: dış dizinin her hücresi bir satır dizisini gösterir; satırlar farklı uzunlukta olabilir (düzensiz dizi).
  • matris.length = satır sayısı, matris[0].length = sütun sayısı.
YığınHeapmatrissatırlar00112231041526matris[1][2] → 6

Matris · Kodu adım adım çalıştır

Düzensiz (Jagged) Dizi: new int[3][]

YığınHeapmdış dizi0null1null2null

new int[3][] yalnızca dış diziyi (3 hücre) oluşturur. Satırlar henüz yok: üç hücre de null.

YığınHeapmdış dizi001null2null

m[0] = new int[1]: ilk hücre 1 öğeli bir satır gösterir. m[1] ve m[2] hâlâ null.

YığınHeapmdış dizi001002null

m[1] = new int[2]: ikinci satır 2 öğeli.

YığınHeapmdış dizi001002000

m[2] = new int[3]: satırlar farklı uzunlukta, yani düzensiz (jagged) dizi. Her satır ayrı bir nesnedir.

YığınHeapmdış dizi00length = 11002000

i = 0: m[0].length = 1 yazılır.

YığınHeapmdış dizi00length = 1100length = 22000

i = 1: m[1].length = 2 yazılır.

YığınHeapmdış dizi00length = 1100length = 22000length = 3

i = 2: m[2].length = 3. Çıktı: 1 2 3. Satır null iken m[i].length yazılsaydı NullPointerException olurdu.

int[][] m = new int[3][];
m[0] = new int[1];
m[1] = new int[2];
m[2] = new int[3];
for (int i = 0; i < m.length; i++)
    System.out.print(m[i].length + " ");

Matris · Kodu adım adım çalıştır

2B Dizide Sığ Kopya Tuzağı

YığınHeapa1234

a, iki satır dizisini gösteren bir dış dizidir.

YığınHeapa1234bsatırlar paylaşılıyor

a.clone() yalnızca dış diziyi kopyalar: iki dış dizi, aynı satır nesnelerini gösterir (sığ kopya).

YığınHeapa99234bsatırlar paylaşılıyor

b[0][0] = 99: b[0] ve a[0] aynı satırdır → a[0][0] da 99 oldu.

YığınHeapa99234b78yeni satıra[0] = b[0] (ortak)

b[1] = new int[]{7, 8} yalnızca b'nin hücresini yeni satıra bağlar; a[1] değişmez.

YığınHeapa99234b78yeni satıra[0] = b[0] (ortak)

a: ortak satır 0 değişti (99), satır 1 hâlâ {3, 4}.

YığınHeapa99234b78yeni satıra[0] = b[0] (ortak)

Gerçek kopya için her satır ayrıca kopyalanır: b[i] = a[i].clone().

int[][] a = {{1, 2}, {3, 4}};
int[][] b = a.clone();
b[0][0] = 99;
b[1] = new int[]{7, 8};
System.out.println(Arrays.deepToString(a));
System.out.println(Arrays.deepToString(b));

Matris · Kodu adım adım çalıştır

Matriste Satır Satır Gezinme

00112231456i ↓ j →

2 satır × 3 sütunluk matris; matris.length = 2.

00112231456i ↓ j →

Dış döngü: 0 < 2 → true → 0. satır işlenecek.

00112231456i ↓ j →

İç döngü: 0 < 3 → true; matris[0][0] = 1 yazılır (print: satır atlamaz).

00112231456i ↓ j →

İç döngü: 1 < 3 → true; matris[0][1] = 2 yazılır (print: satır atlamaz).

00112231456i ↓ j →

İç döngü: 2 < 3 → true; matris[0][2] = 3 yazılır (print: satır atlamaz).

00112231456i ↓ j →

3 < 3 → false: satır bitti, iç döngüden çıkılır.

00112231456i ↓ j →

println() alt satıra geçer; ardından i++.

00112231456i ↓ j →

Dış döngü: 1 < 2 → true → 1. satır işlenecek.

00112231456i ↓ j →

İç döngü: 0 < 3 → true; matris[1][0] = 4 yazılır (print: satır atlamaz).

00112231456i ↓ j →

İç döngü: 1 < 3 → true; matris[1][1] = 5 yazılır (print: satır atlamaz).

00112231456i ↓ j →

İç döngü: 2 < 3 → true; matris[1][2] = 6 yazılır (print: satır atlamaz).

00112231456i ↓ j →

3 < 3 → false: satır bitti, iç döngüden çıkılır.

00112231456i ↓ j →

println() alt satıra geçer; ardından i++.

00112231456i ↓ j →

Dış döngü: 2 < 2 → false → bitti. Toplam 2 × 3 = 6 hücre gezildi.

int[][] matris = {{1, 2, 3}, {4, 5, 6}};
for (int i = 0; i < matris.length; i++) {
  for (int j = 0; j < matris[i].length; j++) {
    System.out.print(matris[i][j] + " ");
  }
  System.out.println();
}

Matris · Kodu adım adım çalıştır

Matris Transpozu

00112231456matris (2×3)

Kaynak matris 2 × 3.

00112231456matris (2×3)

matris.length = satır sayısı = 2.

00112231456matris (2×3)

matris[0].length = ilk satırın uzunluğu = 3.

00112231456matris (2×3)00010100200t (3×2)

Hedef t boyutları ters: 3 × 2, hücreler 0.

00112231456matris (2×3)00110100200t (3×2)

t[0][0] = matris[0][0] = 1: satır ↔ sütun yer değiştirir.

00112231456matris (2×3)00110120200t (3×2)

t[1][0] = matris[0][1] = 2: satır ↔ sütun yer değiştirir.

00112231456matris (2×3)00110120230t (3×2)

t[2][0] = matris[0][2] = 3: satır ↔ sütun yer değiştirir.

00112231456matris (2×3)00114120230t (3×2)

t[0][1] = matris[1][0] = 4: satır ↔ sütun yer değiştirir.

00112231456matris (2×3)00114125230t (3×2)

t[1][1] = matris[1][1] = 5: satır ↔ sütun yer değiştirir.

00112231456matris (2×3)00114125236t (3×2)

t[2][1] = matris[1][2] = 6: satır ↔ sütun yer değiştirir.

00112231456matris (2×3)00114125236t (3×2)

Döngüler bitti: matrisin satırları t'nin sütunları oldu.

int[][] matris = {{1, 2, 3}, {4, 5, 6}};
int satirSayisi = matris.length;
int sutunSayisi = matris[0].length;
int[][] t = new int[sutunSayisi][satirSayisi];
for (int i = 0; i < satirSayisi; i++)
    for (int j = 0; j < sutunSayisi; j++)
        t[j][i] = matris[i][j];

Matris · Kodu adım adım çalıştır

Matris Çarpımı (2×2)

1234A×5678B=0000C

C[i][j] = A'nın i. satırı ile B'nin j. sütununun çarpımlarının toplamı. C sıfırlarla başlar.

1234A×5678B=5000CA[0][0] × B[0][0]= 1 × 5 = 5

C[0][0] += 1 × 5 → 0 + 5 = 5

1234A×5678B=19000CA[0][1] × B[1][0]= 2 × 7 = 14

C[0][0] += 2 × 7 → 5 + 14 = 19 (hücre tamam)

1234A×5678B=19600CA[0][0] × B[0][1]= 1 × 6 = 6

C[0][1] += 1 × 6 → 0 + 6 = 6

1234A×5678B=192200CA[0][1] × B[1][1]= 2 × 8 = 16

C[0][1] += 2 × 8 → 6 + 16 = 22 (hücre tamam)

1234A×5678B=1922150CA[1][0] × B[0][0]= 3 × 5 = 15

C[1][0] += 3 × 5 → 0 + 15 = 15

1234A×5678B=1922430CA[1][1] × B[1][0]= 4 × 7 = 28

C[1][0] += 4 × 7 → 15 + 28 = 43 (hücre tamam)

1234A×5678B=19224318CA[1][0] × B[0][1]= 3 × 6 = 18

C[1][1] += 3 × 6 → 0 + 18 = 18

1234A×5678B=19224350CA[1][1] × B[1][1]= 4 × 8 = 32

C[1][1] += 4 × 8 → 18 + 32 = 50 (hücre tamam)

1234A×5678B=19224350C

Üç iç içe döngü: n×n matris için n³ çarpma → O(n³). Sütun sayısı (A) = satır sayısı (B) olmalı.

int[][] A = {{1, 2}, {3, 4}};
int[][] B = {{5, 6}, {7, 8}};
int[][] C = new int[2][2];
for (int i = 0; i < 2; i++)
  for (int j = 0; j < 2; j++)
    for (int k = 0; k < 2; k++)
      C[i][j] += A[i][k] * B[k][j];

Tasarım

Dizi mi Liste mi?

  • Öğe sayısı baştan belli ve sabitse dizi yeterli ve hızlıdır.
  • Öğe sayısı değişecekse ArrayList gibi koleksiyonlar daha kullanışlıdır.
  • int[] sayıları doğrudan saklar; ArrayList<Integer> her sayıyı bir nesne içinde tutar.
  • Seçim; kullanım biçimine, okunabilirliğe ve ölçülen performansa göre yapılır.
Dizi dolunca büyümez:3856+ 7 ?yeni, büyük dizi + kopyalama38567ArrayList bunu kendisi yapar.

Doğrulama

Yaygın Hatalar

Bir tur fazla

i <= a.length son turda a[length]'e erişir → ArrayIndexOutOfBoundsException. Doğrusu i < a.length.

Boş dizide ilk öğe

int min = a[0]; boş dizide hata verir; önce a.length == 0 kontrolü.

Referans kopyası

int[] b = a; yeni dizi değildir; b[0] = 9 a'yı da değiştirir. Kopya için a.clone().

Düzensiz matris

Her satırın uzunluğu matris[0].length değildir; iç döngüde matris[i].length kullanılır.

i <= a.length → son turda a[5]3081126324✗5a.length = 5 → geçerli indisler 0 … 4int[] b = a; b[0] = 9;ab923tek dizi: a[0] de 9 olur

Özet

Bölüm Özeti

Yapı

Aynı tipte, sabit sayıda öğe; indis 0 … length − 1; değişken diziyi referansla gösterir.

Erişim

a[i] okuma/yazma sabit sürede; sınır dışı indis çalışma zamanı hatası.

Gezinme

Klasik for (indis gerekince) ve gelişmiş for (döngü değişkenine atama diziyi değiştirmez); toplam, min-max, ters çevirme, arama.

Matris

int[][] dizi dizisidir: matris.length satır, matris[i].length sütun sayısı.

Özet

Kontrol Soruları

  1. Beş öğeli dizinin son indisi nedir?
  2. Gelişmiş for ne zaman yetersiz kalır?
  3. Dizi ataması ile öğe kopyası arasındaki fark nedir?
  4. İkili arama için hangi ön koşul gerekir?
  5. matris.length ile matris[0].length neyi verir?
Cevaplar
  1. 4 (length − 1).
  2. İndis gerektiğinde: konumu yazdırmak, hücreye yeni değer yazmak, diziyi tersten veya iki diziyi birlikte gezmek.
  3. Atama (b = a) yalnızca referansı kopyalar, iki değişken aynı nesneyi gösterir; clone/Arrays.copyOf yeni bir dizi oluşturur.
  4. Dizinin sıralı olması.
  5. Satır sayısını ve ilk satırın sütun sayısını.

Özet

Alıştırmalar

  1. Bir int[] dizisindeki çift sayıların adedini ve toplamını bulan kodu yazın.
  2. Diziyi ekstra dizi kullanmadan bir konum sağa döndüren (son öğe başa) kodu yazın: {1,2,3,4} → {4,1,2,3}.
  3. İki sıralı diziyi tek bir sıralı dizide birleştirin ({1,4,7} + {2,3,9}).
  4. Kabarcık sıralamasına, bir geçişte hiç takas olmazsa erken duran bir boolean bayrak ekleyin.
  5. Eratosthenes eleğiyle 100'e kadar kaç asal olduğunu sayın (cevap: 25).
  6. 3×3 bir matrisin ana köşegen toplamını ve transpozunu hesaplayın; matris simetrik mi kontrol edin.

Özet

Kaynaklar

  • Deitel ve Deitel, Java: How to Program, Early Objects, 11. baskı, Pearson, 2018.
  • Liang, Introduction to Java Programming and Data Structures, 13. baskı, Pearson, 2024.
  • Oracle, The Java Tutorials: Arrays.
  • Oracle, Java SE 21 API: java.util.Arrays; Java Language Specification SE 21: Bölüm 10, Arrays.
  • Sedgewick ve Wayne, Computer Science: An Interdisciplinary Approach, Addison-Wesley, 2016: 1.4 Arrays.
  • Cormen, Leiserson, Rivest ve Stein, Introduction to Algorithms, 4. baskı, MIT Press, 2022.

Son

Diziler
Sonraki sunum: Dizgiler · Çalışma soruları · Simülatör: Dizi Laboratuvarı · Terim sözlüğü
1 / 1Sercan KÜLCÜ, Tüm hakları saklıdır.