Bölüm 3.3: Diziler
Giriş
Öğrenme Çıktıları
Dizinin (array) aynı tipten, sabit sayıda öğeyi ardışık hücrelerde tuttuğunu ve öğelere 0'dan başlayan indis ile erişildiğini açıklamak.
Tek ve çok boyutlu dizileri tanımlamak, new ve ilklendirici listesiyle oluşturmak, length ile gezinmek.
Dizi değişkeninin bir referans olduğunu, dizinin heap'te durduğunu; atama, kopyalama ve metoda geçirmenin sonucunu öngörmek.
ArrayIndexOutOfBoundsException ve sık derleme hatalarını tanımak, sınır kontrolüyle önlemek.
Ortalama, ortanca, mod, doğrusal ve ikili arama, eşleştirme, tersine çevirme, seçimli ve kabarcık sıralamasını yazmak; O(1), O(n), O(n²) maliyetlerini karşılaştırmak.
Matrisleri iç içe döngülerle doldurmak, yazdırmak, transpozunu almak ve char[][] ile Tic Tac Toe oyunu kurmak.
Dizi Kavramı
Dizi Nedir?
- Dizi (Array): aynı tipteki verileri düzenli bir şekilde, tek bir ad altında saklayan yapıdır.
- Aynı adla tanımlanan, bir veya daha fazla veri saklayabilen bir değişken gibi düşünülebilir.
- Öğelere indis (index) numarasıyla erişilir; indisleme sayesinde erişim çok hızlıdır.
- İlk öğenin indisi 0'dır; n öğeli dizinin son indisi n − 1'dir.
- Bir öğeye erişmek için dizinin adı ve köşeli parantez içinde indis yazılır:
dizi[0].
Örnek: dizi = [10, 20, 30, 40, 50] ise dizi[0] ilk öğedir ve değeri 10'dur; dizi[4] son öğedir (50).
Dizi Kavramı
Neden Dizi?
Dizisiz: 50 öğrenci için 50 değişken
int not1 = 70; int not2 = 85; int not3 = 90; // ... not50'ye kadar int toplam = not1 + not2 + not3 /* + ... */;
Ortalamayı hesaplamak için 50 ismi tek tek yazmak gerekir; öğrenci sayısı değişirse kod da değişir.
Diziyle: tek ad, döngüyle işlem
int[] notlar = new int[50]; // ... notlar doldurulur int toplam = 0; for (int i = 0; i < notlar.length; i++) { toplam += notlar[i]; }
Aynı kod 5 ya da 5000 not için çalışır: indis bir değişken olabilir (notlar[i]), döngü tüm öğeler üzerinde gezinir.
notlar[i] yazıldığında hangi hücreye bakılacağı çalışma zamanında i'nin değerine göre belirlenir.Dizi Kavramı
Bellekte Bir Dizi
Aşağıdaki görsel, beş öğeli tek boyutlu bir diziyi temsil eder. Her öğe bir hücrede durur; hücreler bellekte yan yana (ardışık) yerleşir.
| indis | 0 | 1 | 2 | 3 | 4 |
|---|---|---|---|---|---|
| öğe | 13 | −1 | 4 | 2 | 7 |
a[1] = −1, a[4] = 7, a.length = 5. a[5] diye bir hücre yoktur: geçerli indisler 0…4'tür.
Dizi Kavramı
Avantajlar ve Dezavantajlar
- Verileri düzenli ve ardışık bir şekilde saklar.
- İndisleme ile öğelere hızlı erişim sağlar:
dizi[i]her i için aynı sürede okunur. - Verileri gruplandırarak düzenlemeye olanak sağlar; döngülerle kolayca işlenir.
- Bellek kullanımı yalındır: yalnızca öğeler ve uzunluk tutulur.
- Sabit boyutludur: oluşturulduktan sonra boyutu değiştirilemez.
- Yer kalmadığında öğe eklemek için daha büyük yeni bir dizi oluşturup kopyalamak gerekir.
- Ortaya ekleme veya ortadan silme, öğeleri kaydırmayı gerektirir (ek maliyet).
- Yalnızca tek tipten öğe tutar.
Boyutu değişen listeler için Java'da ArrayList vardır; içinde yine bir dizi kullanır ve dolunca büyütür (java.util koleksiyonları).
Dizi Kavramı
Dizi Türleri ve Kullanım Alanları
int[] notlarint[][] tabloint[][][] kupKullanım alanları
- Programlama dillerinde en yaygın veri yapısıdır; verileri düzenlemek ve işlemek için idealdir.
- Ölçümler: bir sensörden saniyede alınan örnekler, ses sinyali (
double[]). - Matrisler: devre analizi, doğrusal denklem sistemleri.
- Resimler: piksel ızgarası (
int[yukseklik][genislik]).
Java'da Diziler
Dizi Tanımlama
VeriTipi[] diziAdi = new VeriTipi[diziBoyutu];int, double, char, String…int.int[] sayilar = new int[5]; // 5 tamsayı double[] olcum = new double[100]; // 100 ondalık String[] isimler = new String[30]; int n = 12; char[] harfler = new char[n]; // boyut değişkenden int dizi2[] = new int[3]; // C tarzı, geçerli ama önerilmez
| Tip | Varsayılan değer |
|---|---|
int, long… | 0 |
double | 0.0 |
boolean | false |
char | '\u0000' (kod 0) |
String ve nesneler | null |
Java'da Diziler
Erişim ve length
- Dizi öğelerine indis ile erişilir; indis 0'dan başlar.
dizi[i]hem okumak hem yazmak için kullanılır.- Dizinin boyutu
lengthözelliği ile alınır: dizinin kaç öğe içerdiğini verir. lengthbir metot değildir: parantez yok (String'dekilength()ise bir metottur).- Son öğe her zaman
dizi[dizi.length - 1]'dir.
int[] sayilar = {10, 20, 30, 40, 50}; int ilkEleman = sayilar[0]; // İlk elemanı alır int ikinciEleman = sayilar[1]; // İkinci elemanı alır int diziBoyutu = sayilar.length; // 5 System.out.println(ilkEleman + " " + ikinciEleman + " " + diziBoyutu); sayilar[1] = 25; // yazma int son = sayilar[sayilar.length - 1]; // 50
Çıktı
10 20 5
Java'da Diziler
Dizi İlk Değer Verme
- Dizi tanımlanırken öğelerine başlangıç değeri atanabilir: ilklendirici listesi (array initializer).
- Bu durumda boyut belirtilmez; ilklendiriciler boyutu belirler: 5 değer varsa dizi 5 öğeli olur.
int[] sayilar = {10, 20, 30, 40, 50}; // 5 elemanlı int[] n = {1, 2, 3, 4, 5}; // 5 değer olduğundan n 5 elemanlı bir dizi olur int[] m = new int[]{1, 2, 3}; // uzun biçim: her yerde kullanılabilir String[] gunler = {"Pzt", "Sal", "Çar"}; char[] sesli = {'a', 'e', 'ı', 'i', 'o', 'ö', 'u', 'ü'};
a = {1, 2, 3}; yazılamaz (illegal start of expression). Bunun yerine a = new int[]{1, 2, 3}; yazılır.new int[3]{1, 2, 3} derlenmez: ya boyut ya liste verilir.Java'da Diziler
Örnek: DiziOrnegi
public class DiziOrnegi { public static void main(String[] args) { // Bir diziyi tanımlama: 5 elemanlı bir tamsayı dizisi int[] sayilar = new int[5]; // Dizinin elemanlarına değer atama sayilar[0] = 10; sayilar[1] = 20; sayilar[2] = 30; sayilar[3] = 40; sayilar[4] = 50; // Dizinin elemanlarına erişme System.out.println("birinci eleman: " + sayilar[0]); System.out.println("ucuncu eleman: " + sayilar[2]); // Dizinin tüm elemanlarını döngü içerisinde yazdırma System.out.print("Elemanlar: "); for (int i = 0; i < sayilar.length; i++) { System.out.print(sayilar[i] + " "); } } }
Çıktı
birinci eleman: 10 ucuncu eleman: 30 Elemanlar: 10 20 30 40 50
for (int i = 0; i < dizi.length; i++) dizinin tüm indisleri üzerinde 0'dan length − 1'e kadar gezinir. <= yazmak sık yapılan bir hatadır.Java'da Diziler · Adım adım kod izleme
DiziOrnegi: Kodu Adım Adım İzle
new int[5] heap'te 5 hücrelik bir dizi oluşturur; her hücre varsayılan değer 0 ile başlar. sayilar bu dizinin referansını tutar.
sayilar[0] = 10; → 1. hücreye (indis 0) yazılır.
sayilar[1] = 20; → 2. hücreye (indis 1) yazılır.
sayilar[2] = 30; → 3. hücreye (indis 2) yazılır.
sayilar[3] = 40; → 4. hücreye (indis 3) yazılır.
sayilar[4] = 50; → 5. hücreye (indis 4) yazılır.
Birinci öğenin indisi 0'dır: sayilar[0] okunur → 10.
Üçüncü öğe sayilar[2]'dir (indis = sıra − 1) → 30.
print alt satıra geçmez; öğeler aynı satıra yazılacak.
i = 0: 0 < 5 doğru → sayilar[0] = 10 yazılır.
i = 1: 1 < 5 doğru → sayilar[1] = 20 yazılır.
i = 2: 2 < 5 doğru → sayilar[2] = 30 yazılır.
i = 3: 3 < 5 doğru → sayilar[3] = 40 yazılır.
i = 4: 4 < 5 doğru → sayilar[4] = 50 yazılır.
i = 5: 5 < sayilar.length yanlış → döngü biter. Son geçerli indis length − 1 = 4'tür.
int[] sayilar = new int[5]; sayilar[0] = 10; sayilar[1] = 20; sayilar[2] = 30; sayilar[3] = 40; sayilar[4] = 50; System.out.println("birinci eleman: " + sayilar[0]); System.out.println("ucuncu eleman: " + sayilar[2]); System.out.print("Elemanlar: "); for (int i = 0; i < sayilar.length; i++) { System.out.print(sayilar[i] + " "); }
Java'da Diziler
for-each Döngüsü
int[] notlar = {70, 85, 90}; // Klasik for: indis elimizde for (int i = 0; i < notlar.length; i++) { System.out.println(i + ". not: " + notlar[i]); } // for-each: yalnızca değerler int toplam = 0; for (int not : notlar) { toplam += not; } System.out.println("Toplam: " + toplam);
Çıktı
0. not: 70 1. not: 85 2. not: 90 Toplam: 245
- Gelişmiş for (enhanced for / for-each):
for (tür eleman : dizi)her turda sıradaki öğeyielemandeğişkenine koyar. - İndis yazılmaz; bu yüzden sınır dışı hatası yapılamaz.
- Yalnızca okumak içindir:
not = 0;yazmak dizideki öğeyi değiştirmez, yalnızca kopyayı değiştirir. - İndise ihtiyaç varsa (yazmak, konum bildirmek, iki komşuyu karşılaştırmak) klasik
forkullanılır.
Java'da Diziler · Adım adım kod izleme
for-each: Değer Gelir, Hücre Gelmez
Heap'te üç hücreli bir dizi var; puanlar onun referansını tutar.
toplam 0 ile başlar.
İlk tur: döngü puanlar[0]'ın kopyasını p'ye koyar, p = 60. İndis yazılmaz.
toplam += p → 60.
İkinci tur: p = 75 (sıradaki öğeyi döngü kendisi verir).
toplam = 60 + 75 = 135.
Son tur: p = 95.
toplam = 230. Öğe kalmadı, döngü biter.
Toplam: 230 yazılır.
İkinci döngü: p yine puanlar[0]'ın kopyası, 60.
p = 0 yalnızca kopyayı değiştirir; dizideki 60 yerinde durur. Kalan turlar da aynıdır.
60 95: dizi hiç değişmedi. for-each ile diziye yazılamaz; yazmak için klasik for ve puanlar[i] gerekir.
int[] puanlar = {60, 75, 95}; int toplam = 0; for (int p : puanlar) { toplam += p; } System.out.println("Toplam: " + toplam); for (int p : puanlar) { p = 0; } System.out.println(puanlar[0] + " " + puanlar[2]);
Java'da Diziler
Sıcaklık Dönüşümü: Dizi ve for-each
double[] celsiuslar = {-40, 0, 25, 100}; for (double celsius : celsiuslar) { double fahrenheit = (celsius * 1.8) + 32; double kelvin = celsius + 273.15; System.out.println(celsius + " °C = " + fahrenheit + " °F = " + kelvin + " K"); }
-40.0 °C = -40.0 °F = 233.14999999999998 K 0.0 °C = 32.0 °F = 273.15 K 25.0 °C = 77.0 °F = 298.15 K 100.0 °C = 212.0 °F = 373.15 K
double[] celsiuslar = {…};dört değeri bir dizide (array) toplar.- for-each döngüsü:
for (double celsius : celsiuslar)“dizideki her öğe için” demektir;celsiusher turda sıradaki öğeyi alır. - Gövde 4 kez çalışır; tablo tek seferde üretilir.
233.14999999999998: ondalıklı sayılar ikili tabanda tam saklanamaz, küçük yuvarlama hataları olur. Yazdırırkenprintfile basamak sınırlanabilir.
Java'da Diziler · Adım adım kod izleme
for-each ile Sıcaklık Tablosu
Dizide dört Celsius değeri var (indis 0–3). for-each döngüsü onları sırayla celsius'a kopyalayacak.
Sıradaki öğe (indis 0) celsius'a kopyalanır: celsius = -40.0.
-40.0 × 1.8 + 32 = -40.0 °F, -40.0 + 273.15 = 233.14999999999998 K. Kelvin'de 233.14999999999998: ondalıklı sayının ikili tabanda yaklaşık saklanması.
Satır yazdırılır; gövde biter, döngü sıradaki öğeye geçer.
Sıradaki öğe (indis 1) celsius'a kopyalanır: celsius = 0.0.
0.0 × 1.8 + 32 = 32.0 °F, 0.0 + 273.15 = 273.15 K.
Satır yazdırılır; gövde biter, döngü sıradaki öğeye geçer.
Sıradaki öğe (indis 2) celsius'a kopyalanır: celsius = 25.0.
25.0 × 1.8 + 32 = 77.0 °F, 25.0 + 273.15 = 298.15 K.
Satır yazdırılır; gövde biter, döngü sıradaki öğeye geçer.
Sıradaki öğe (indis 3) celsius'a kopyalanır: celsius = 100.0.
100.0 × 1.8 + 32 = 212.0 °F, 100.0 + 273.15 = 373.15 K.
Son satır yazdırılır.
Dizide öğe kalmadı: döngü biter. Gövde 4 kez çalıştı; indis değişkeni hiç yazılmadı.
double[] celsiuslar = {-40, 0, 25, 100}; for (double celsius : celsiuslar) { double fahrenheit = (celsius * 1.8) + 32; double kelvin = celsius + 273.15; System.out.println(celsius + " °C = " + fahrenheit + " °F = " + kelvin + " K"); }
Java'da Diziler · Adım adım kod izleme
Dizi Değişkeni Bir Referanstır
Heap'te bir dizi oluşur; a değişkeninde dizinin kendisi değil, adresi (referansı) vardır.
b = a yalnızca adresi kopyalar. Artık iki değişken aynı diziyi gösterir (takma ad, alias).
b[0] = 99 ortak diziyi değiştirir…
…bu yüzden a[0] da 99 olur.
clone() heap'te yeni bir dizi oluşturup öğeleri kopyalar; c bu yeni diziyi gösterir.
c[1] = 77 yalnızca kopyayı değiştirir; asıl dizi etkilenmez.
a[1] hâlâ 2, c[1] ise 77.
== referansları (adresleri) karşılaştırır: a == b doğru (aynı dizi), a == c yanlış (farklı diziler).
int[] a = {1, 2, 3}; int[] b = a; // kopya değil! b[0] = 99; System.out.println(a[0]); int[] c = a.clone(); // gerçek kopya c[1] = 77; System.out.println(a[1] + " " + c[1]); System.out.println(a == b); System.out.println(a == c);
Java'da Diziler
java.util.Arrays Sınıfı
int[] dizi = {5, 3, 8, 1}; System.out.println(Arrays.toString(dizi)); Arrays.sort(dizi); System.out.println(Arrays.toString(dizi)); int[] kopya = Arrays.copyOf(dizi, 6); System.out.println(Arrays.toString(kopya)); int[] dolu = new int[4]; Arrays.fill(dolu, 7); System.out.println(Arrays.toString(dolu)); int[] x = {1, 2}; int[] y = {1, 2}; System.out.println((x == y) + " " + Arrays.equals(x, y)); System.out.println(Arrays.binarySearch(dizi, 5));
Çıktı
[5, 3, 8, 1] [1, 3, 5, 8] [1, 3, 5, 8, 0, 0] [7, 7, 7, 7] false true 2
Metot (import java.util.Arrays;) | Görevi |
|---|---|
Arrays.toString(d) | Diziyi metne çevirir; println(d) ise [I@7ef20235 gibi bir kimlik yazar |
Arrays.sort(d) · binarySearch | Yerinde sıralar · sıralı dizide indis arar (5 → 2); dizilerde indexOf yoktur |
Arrays.copyOf(d, n) · d.clone() | Yeni dizi oluşturup kopyalar; fazla hücreler 0 olur |
Arrays.fill · Arrays.equals | Tüm hücrelere aynı değeri yazar · içerikleri karşılaştırır (== adres karşılaştırır) |
Bellek ve Hatalar
Diziler Bellekte Nerede?
String[] plaka = {"", "Adana", "Adıyaman", "Afyon"};
System.out.println(plaka[1]);
int[] dinamikDizi = new int[10]; // heap'te yer ayrılır
System.out.println(dinamikDizi.length);
dinamikDizi = null; // referans koparıldı
System.out.println(dinamikDizi == null);- C/C++'ta
int a[10];yığında durur;malloc/newile heap'te ayrılan dizi elle serbest bırakılır. - Çıktı:
Adana,10,true. - Java'da tüm diziler heap'tedir; boyut çalışma zamanında verilebilir, sonra sabittir. Serbest bırakma otomatiktir.
Her iki dizi de heap'te oluşur; yığında (stack) yalnızca referans değişkenleri durur. (String[] hücreleri de aslında ayrı String nesnelerine referanstır.)
dinamikDizi = null diziyi silmez, yalnızca bağı koparır. Dizi artık erişilemez olduğundan çöp toplayıcı (garbage collector) uygun bir anda belleği geri alır.
Metot bitince yığın çerçevesi ve içindeki referanslar otomatik kalkar. Başka referans kalmayan diziler de zamanla toplanır. Java'da free/delete yoktur.
Bellek ve Hatalar
İndis Sınır Dışı Hatası
- Dizinin sınırları (0 … length − 1) dışındaki bir indise erişildiğinde Java çalışma zamanında
ArrayIndexOutOfBoundsExceptionfırlatır (IndexOutOfBoundsException'ın alt sınıfı). - Yakalanmazsa program o satırda çöker; C'deki gibi sessizce başka bir belleği bozmaz.
int[] dizi = {10, 20, 30, 40, 50}; int index = 5; // Dizi uzunluğunu kontrol etme if (index >= 0 && index < dizi.length) { int deger = dizi[index]; System.out.println("Değer: " + deger); } else { System.out.println("Geçersiz indis: " + index); } // Kontrolsüz erişim: System.out.println(dizi[index]);
Çıktı
Geçersiz indis: 5 Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 5 at SinirDisi.main(SinirDisi.java:13)
Mesaj; hatalı indisi (5), dizinin uzunluğunu (5) ve satır numarasını söyler: hatayı bulmak için ilk bakılacak yer.
Bellek ve Hatalar
Klasik Hata: <= ile Döngü
int[] dizi = new int[3]; for (int i = 0; i <= dizi.length; i++) { dizi[i] = i * 10; }
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3 at SinirDongu.main(SinirDongu.java:5)
i = 3olduğunda koşul3 <= 3doğru kalır vedizi[3]yazılmaya çalışılır.- Doğru koşul
i < dizi.length; sabit sayı (i < 3) yerinelengthkullanılırsa boyut değişince kod bozulmaz.
Bellek ve Hatalar · Adım adım kod izleme
<= ile Döngü: Hata Hangi Turda?
4 hücreli dizi; geçerli indisler 0 … 3, kare.length = 4.
i = 0: koşul 0 <= 4 doğru.
kare[0] = 0.
i = 1: 1 <= 4 doğru.
kare[1] = 1.
i = 2: doğru.
kare[2] = 4.
i = 3: doğru.
kare[3] = 9: son geçerli hücre doldu.
i = 4: 4 <= 4 de doğru! < yazılsaydı döngü burada biterdi.
kare[4] yok: JVM ArrayIndexOutOfBoundsException fırlatır, program bu satırda durur; “bitti” hiç yazılmaz.
int[] kare = new int[4]; for (int i = 0; i <= kare.length; i++) { kare[i] = i * i; } System.out.println("bitti");
İstatistik Örnekleri
Kullanıcıdan Dizi Okuma
import java.util.Scanner; public class OrtalamaHesaplama { public static void main(String[] args) { // Kullanıcıdan dizi boyutunu al Scanner scanner = new Scanner(System.in); System.out.print("boyutu girin: "); int boyut = scanner.nextInt(); // Kullanıcıdan elemanları al ve dizi oluştur double[] dizi = new double[boyut]; for (int i = 0; i < boyut; i++) { System.out.print((i + 1) + ". elemani girin: "); dizi[i] = scanner.nextDouble(); } // ... diziyle hesaplamalar } }
Örnek çalışma (girdiler kalın)
boyutu girin: 4 1. elemani girin: 7 2. elemani girin: 3 3. elemani girin: 9 4. elemani girin: 5
- Dizi boyutu kullanıcıdan gelir:
new double[boyut]. Boyut çalışma zamanında belirlenir, sonra değişmez. - İstemde
i + 1yazılır (kullanıcı 1'den sayar), diziyedizi[i]ile yazılır (0'dan). - Ortalama, ortanca ve mod programları bu okuma bölümüyle başlar.
İstatistik Örnekleri · Adım adım kod izleme
OrtalamaHesaplama: Kodu Adım Adım İzle
Kullanıcı boyut olarak 4 girer.
nextInt() klavyeden bir tam sayı okur: boyut = 4. Dizinin boyutu ancak şimdi, çalışma zamanında belli oldu.
new double[boyut]: 4 hücreli dizi, hepsi 0.0.
i = 0: istem 1. elemani girin: yazılır, kullanıcı 7 girer → dizi[0] = 7.0.
i = 1: istem 2. elemani girin: yazılır, kullanıcı 3 girer → dizi[1] = 3.0.
i = 2: istem 3. elemani girin: yazılır, kullanıcı 9 girer → dizi[2] = 9.0.
i = 3: istem 4. elemani girin: yazılır, kullanıcı 5 girer → dizi[3] = 5.0.
toplam += dizi[0] → toplam = 7.0.
toplam += dizi[1] → toplam = 10.0.
toplam += dizi[2] → toplam = 19.0.
toplam += dizi[3] → toplam = 24.0.
ortalama = 24.0 / 4 = 6.0. toplam double olduğu için bölme ondalıklıdır.
İkinci döngü öğeleri yan yana yazar; double değerler 7.0 biçiminde görünür. Sonra println() satırı bitirir.
Sonuç yazdırılır.
Scanner scanner = new Scanner(System.in); System.out.print("boyutu girin: "); int boyut = scanner.nextInt(); double[] dizi = new double[boyut]; for (int i = 0; i < boyut; i++) { System.out.print((i + 1) + ". elemani girin: "); dizi[i] = scanner.nextDouble(); } double toplam = 0; for (int i = 0; i < boyut; i++) { toplam += dizi[i]; } double ortalama = toplam / boyut; System.out.print("Elemanlar: "); for (int i = 0; i < boyut; i++) { System.out.print(dizi[i] + " "); } System.out.println(); System.out.println("Ortalama: " + ortalama);
İstatistik Örnekleri
OrtancaDegerHesaplama
// boyut ve dizi, OrtalamaHesaplama'daki gibi okunur Arrays.sort(dizi); // Diziyi sırala double ortanca; if (boyut % 2 == 0) { // Çift sayıda eleman int orta1 = boyut / 2 - 1; int orta2 = boyut / 2; ortanca = (dizi[orta1] + dizi[orta2]) / 2; } else { // Tek sayıda eleman ortanca = dizi[boyut / 2]; } System.out.println("Ortanca Değer: " + ortanca);
Örnek çalışma
girilenler: 7 3 9 5 1 Elemanlar (sirali): 1.0 3.0 5.0 7.0 9.0 Ortanca Değer: 5.0
ortanca dalların dışında tanımlanmalıdır; yalnızca dalların içinde tanımlanırsa derleyici error: cannot find symbol … variable ortanca verir. import java.util.Arrays; gerekir.
İstatistik Örnekleri
Ortanca: Tek ve Çift Boyut
Girilen değerler sırasızdır: ortadaki hücre (9.0) ortanca değildir.
Arrays.sort(dizi) sonrası. Boyut 5 (tek): dizi[5 / 2] = dizi[2] → ortanca 5.0. Tam sayı bölmesi 2.5'i 2'ye keser.
Boyut 4 (çift; girdiler 7 3 9 5): orta1 = 4/2 − 1 = 1, orta2 = 4/2 = 2 → (5.0 + 7.0) / 2 = 6.0.
Arrays.sort diziyi yerinde değiştirir; girilen sıra kaybolur. Sırayı korumak için önce dizi.clone() alınır.İstatistik Örnekleri
ModHesaplama
- Önce
Arrays.sort(dizi): eşit değerler yan yana gelir. - Sonra tek geçişte en uzun "seri" bulunur: her öğe bir öncekiyle karşılaştırılır.
Sonucu yazdırma ve çıktı (girdiler: 7, sonra 4 2 7 2 4 2 9)
// Sonucu yazdır
System.out.println("Elemanlar sirali: " + Arrays.toString(dizi));
System.out.print("Mod: " + enCokTekrarEden);
System.out.println(" (Tekrar Sayisi: " + enCokTekrarSayisi + ")");Elemanlar sirali: [2, 2, 2, 4, 4, 7, 9] Mod: 2 (Tekrar Sayisi: 3)
İstatistik Örnekleri · Adım adım kod izleme
Mod: Seri Sayma Adım Adım
Dizi önceden sıralandı: eşit değerler artık yan yana. İlk öğe hem mevcut hem en çok tekrar eden aday (1 kez).
dizi[1] = 2 == dizi[0] = 2 → seri devam ediyor, mevcutTekrarSayisi = 2. 2 > önceki en iyi → en çok tekrar eden 2 (2 kez).
dizi[2] = 2 == dizi[1] = 2 → seri devam ediyor, mevcutTekrarSayisi = 3. 3 > önceki en iyi → en çok tekrar eden 2 (3 kez).
dizi[3] = 4 ≠ dizi[2] = 2 → yeni seri başlıyor: mevcutTekrarEden = 4, sayaç 1.
dizi[4] = 4 == dizi[3] = 4 → seri devam ediyor, mevcutTekrarSayisi = 2.
dizi[5] = 7 ≠ dizi[4] = 4 → yeni seri başlıyor: mevcutTekrarEden = 7, sayaç 1.
dizi[6] = 9 ≠ dizi[5] = 7 → yeni seri başlıyor: mevcutTekrarEden = 9, sayaç 1.
i = 7: döngü biter. Mod = 2, 3 kez tekrar ediyor. Eşit uzunlukta seriler olsaydı > kullanıldığı için ilk bulunan korunurdu.
int enCokTekrarEden = dizi[0]; int enCokTekrarSayisi = 1; int mevcutTekrarEden = dizi[0]; int mevcutTekrarSayisi = 1; for (int i = 1; i < boyut; i++) { if (dizi[i] == dizi[i - 1]) { mevcutTekrarSayisi++; } else { mevcutTekrarSayisi = 1; mevcutTekrarEden = dizi[i]; } if (mevcutTekrarSayisi > enCokTekrarSayisi) { enCokTekrarSayisi = mevcutTekrarSayisi; enCokTekrarEden = mevcutTekrarEden; } }
Dizi Algoritmaları · Adım adım kod izleme
Doğrusal (Lineer) Arama
Bir dizinin içinde belirli bir öğeyi aramanın en basit yolu: baştan sona sırayla her öğeye bakmak.
main, lineerArama(dizi, 30)'u çağırır. Metoda dizinin referansı ve 30 gider.
eleman = 10: 10 == 30 yanlış → sıradaki öğeye geç.
eleman = 20: 20 == 30 yanlış → sıradaki öğeye geç.
eleman = 30: 30 == 30 → doğru. Döngü yarıda kesilir, true döner.
Metot çerçevesi yığından çıkar: sonuc = true. 3 karşılaştırma yetti; 40 ve 50'ye hiç bakılmadı. Hedef 35 olsaydı 5 karşılaştırmadan sonra false dönerdi.
static boolean lineerArama(int[] dizi, int hedef) { for (int eleman : dizi) { if (eleman == hedef) { return true; } } return false; } // main içinde: int[] dizi = {10, 20, 30, 40, 50}; boolean sonuc = lineerArama(dizi, 30);
Dizi Algoritmaları
Doğrusal Aramanın Maliyeti
- En kötü durumda tüm dizi gezilir: n öğeli dizide n karşılaştırma.
- Zaman karmaşıklığı O(n)'dir (n: dizinin boyutu); iş miktarı girdi boyutuyla doğru orantılı büyür.
- İyi durum: hedef erken bulunur (ör. ilk öğe), arama hızlı biter: 1 karşılaştırma.
- Kötü durum: hedef dizinin sonundadır ya da hiç yoktur, arama uzun sürer.
- Sırasız bir dizide daha iyisi yoktur: her öğeye bakmadan "yok" denemez.
int[] dizi = {10, 20, 30, 40, 50}; // Bir dizide belirli bir elemanı arama int aranan = 30; boolean bulundu = false; for (int eleman : dizi) { if (eleman == aranan) { bulundu = true; break; } } // Bu işlem O(n) karmaşıklığına sahiptir.
break, hedef bulunduğu anda döngüden çıkar. Bu örnekte yalnızca 3 öğeye bakılır ve bulundu = true olur.
Dizi Algoritmaları
İkili (Binary) Arama
static int ikiliAra(int[] dizi, int hedef) { int alt = 0, ust = dizi.length - 1; while (alt <= ust) { int orta = (alt + ust) / 2; if (dizi[orta] == hedef) { return orta; // bulundu } else if (hedef < dizi[orta]) { ust = orta - 1; // sol yarı } else { alt = orta + 1; // sağ yarı } } return -1; // alan tükendi } // main içinde: int[] dizi = {3, 9, 14, 27, 42, 48, 55, 61, 70}; System.out.println(ikiliAra(dizi, 48)); System.out.println(ikiliAra(dizi, 50));
Çıktı
5 -1
- Yalnızca sıralı dizide çalışır: ortadaki öğeye bakılır, hedef küçükse sol yarı, büyükse sağ yarı aranır.
- 48 için orta indisler 4 (42), 6 (55), 5 (48): 3 karşılaştırma. 50 için 6 > 5 olunca alan boşalır,
-1döner. - Her adımda arama alanı yarıya iner: O(log n). n = 1000 için en çok 10, n = 1 000 000 için en çok 20 karşılaştırma.
Arrays.binarySearchaynı yöntemi kullanır; sıralanmamış dizide sonucu anlamsızdır.
Dizi Algoritmaları · Adım adım kod izleme
Eşleştirme: Ortak Öğeler
Çağrı: eslestir(new int[]{3, 7, 1}, new int[]{5, 1, 3, 8})
Dış döngü eleman1 = 3: iç döngü dizi2'nin 4 öğesinin hepsiyle karşılaştırır. Eşleşme bulundu → yazdırılır.
Dış döngü eleman1 = 7: iç döngü dizi2'nin 4 öğesinin hepsiyle karşılaştırır. Eşleşme yok.
Dış döngü eleman1 = 1: iç döngü dizi2'nin 4 öğesinin hepsiyle karşılaştırır. Eşleşme bulundu → yazdırılır.
Toplam 3 × 4 = 12 karşılaştırma. Diziler n öğeliyse n × n = n² karşılaştırma yapılır.
static void eslestir(int[] dizi1, int[] dizi2) { for (int eleman1 : dizi1) { for (int eleman2 : dizi2) { if (eleman1 == eleman2) { System.out.println("Eslesen Eleman: " + eleman1); } } } }
Dizi Algoritmaları
Karmaşıklık: O(1), O(n), O(n²)
Neden erişim O(1)?
Hücreler ardışık ve eşit boyutlu (int = 4 bayt) olduğu için i. öğenin adresi tek bir çarpma ve toplama ile hesaplanır: adres = başlangıç + i × 4. dizi[2] ile dizi[1000000] aynı sürede okunur.
| İşlem | Karmaşıklık | n = 1000 için |
|---|---|---|
Erişim dizi[i] | O(1) sabit | 1 |
| Doğrusal arama | O(n) lineer | ≤ 1000 |
| Tersine çevirme | O(n) | 500 takas |
| Eşleştirme (iç içe) | O(n²) karesel | 1 000 000 |
| Seçimli sıralama | O(n²) | ≈ 500 000 |
Dizi Algoritmaları
Seçimli Sıralama
static void secimliSirala(int[] dizi) { for (int i = 0; i < dizi.length - 1; i++) { int minIndeks = i; for (int j = i + 1; j < dizi.length; j++) { if (dizi[j] < dizi[minIndeks]) { minIndeks = j; } } int gecici = dizi[minIndeks]; dizi[minIndeks] = dizi[i]; dizi[i] = gecici; } }
- Seçimli sıralama (Selection Sort): her adımda en küçük öğe bulunup sıralanmamış kısmın başına yerleştirilir.
- Dış döngü n − 1 tur, iç döngü kalan öğeleri tarar → O(n²) karşılaştırma, en fazla n − 1 takas.
- Takas dizi içinde, geçici değişkenle yapılır.
yerDegistir(int x, int y) biçiminde bir takas metodu çalışmaz: metoda öğelerin yalnızca kopyaları gider. Çalışan sürüm dizinin kendisini alır: yerDegistir(int[] d, int i, int j).Dizi Algoritmaları · Adım adım kod izleme
{64, 25, 12, 22, 11} Sıralanıyor
Başlangıç: hiçbir öğe yerinde değil. Her turda kalan kısmın en küçüğü bulunup kalan kısmın başına konur.
Tur i = 0: iç döngü j = 1…4 arasında en küçük değeri arar → 11 (indis 4).
dizi[0] ile dizi[4] yer değiştirdi. İlk 1 hücre artık kesin yerinde.
Tur i = 1: iç döngü j = 2…4 arasında en küçük değeri arar → 12 (indis 2).
dizi[1] ile dizi[2] yer değiştirdi. İlk 2 hücre artık kesin yerinde.
Tur i = 2: iç döngü j = 3…4 arasında en küçük değeri arar → 22 (indis 3).
dizi[2] ile dizi[3] yer değiştirdi. İlk 3 hücre artık kesin yerinde.
Tur i = 3: iç döngü j = 4…4 arasında en küçük değeri arar → 25 (indis 3).
En küçük zaten yerinde; kendisiyle takas edilir (değişiklik yok). 4 tur sonunda son öğe de kendiliğinden yerindedir: dizi sıralı.
int[] dizi = {64, 25, 12, 22, 11}; secimliSirala(dizi); // secimliSirala her turun sonunda yazdırır: // System.out.println("i=" + i + ": " // + Arrays.toString(dizi));
Dizi Algoritmaları
Kabarcık Sıralaması
static void kabarcikSirala(int[] dizi) { int n = dizi.length; for (int tur = 0; tur < n - 1; tur++) { boolean degisti = false; for (int j = 0; j < n - 1 - tur; j++) { if (dizi[j] > dizi[j + 1]) { // ters sıra int gecici = dizi[j]; dizi[j] = dizi[j + 1]; dizi[j + 1] = gecici; degisti = true; } } System.out.println(Arrays.toString(dizi)); if (!degisti) break; // takas yok: sıralı } }
Çıktı: {64, 25, 12, 22, 11, 36, 48}
[25, 12, 22, 11, 36, 48, 64] [12, 22, 11, 25, 36, 48, 64] [12, 11, 22, 25, 36, 48, 64] [11, 12, 22, 25, 36, 48, 64] [11, 12, 22, 25, 36, 48, 64]
- Kabarcık sıralaması (Bubble Sort): komşu iki öğe ters sıradaysa takas edilir; her turda en büyük öğe sona “kabarcık gibi” çıkar.
- Her satır bir turun sonucudur. Her turdan sonra en büyük öğe sona yerleştiği için iç döngü
n - 1 - tur'a kadar gider. degistibayrağı: takas olmayan 5. turda dizi sıralıdır,breakile erken durulur. Sıralı dizide tek tur yeter: O(n).- En kötü durumda yine O(n²) karşılaştırma; seçimli sıralamadan farkı, takas sayısının da O(n²) olabilmesidir.
Dizi Algoritmaları
Diziyi Tersine Çevirme
static void tersineCevir(int[] dizi) { int baslangic = 0; int bitis = dizi.length - 1; while (baslangic < bitis) { // Başlangıç ve bitiş elemanlarını değiştir int gecici = dizi[baslangic]; dizi[baslangic] = dizi[bitis]; dizi[bitis] = gecici; // Başlangıç indeksini artır, bitiş indeksini azalt baslangic++; bitis--; } }
- İki işaretçi (two pointers) tekniği: biri baştan, biri sondan gelir; her turda uçtaki iki öğe takas edilir.
- Yaklaşık n/2 takas → O(n); ek dizi gerekmez (yerinde, in-place).
- Metot
void'dir, ama dizi referansla geldiği için çağıranın dizisi değişir.
Çıktı
[1, 2, 3, 4, 5] → [5, 4, 3, 2, 1] [1, 2, 3, 4] → [4, 3, 2, 1]
Dizi Algoritmaları · Adım adım kod izleme
tersineCevir: Adım Adım
İki işaretçi: baslangic = 0 soldan, bitis = length − 1 = 4 sağdan başlar.
0 < 4 → gecici yardımıyla dizi[0] ile dizi[4] yer değiştirir (gecici = 1).
1 < 3 → gecici yardımıyla dizi[1] ile dizi[3] yer değiştirir (gecici = 2).
baslangic = bitis = 2: 2 < 2 yanlış → döngü biter; ortadaki öğe yerinde kalır. Metot hiçbir şey döndürmez ama çağıranın dizisi değişmiştir: [5, 4, 3, 2, 1].
static void tersineCevir(int[] dizi) { int baslangic = 0; int bitis = dizi.length - 1; while (baslangic < bitis) { int gecici = dizi[baslangic]; dizi[baslangic] = dizi[bitis]; dizi[bitis] = gecici; baslangic++; bitis--; } }
Çok Boyutlu Diziler
İki Boyutlu Diziler (Matrisler)
- Çok boyutlu diziler, birden fazla boyutta veri saklamak için kullanılır; Java iki (matris) ve daha fazla boyutlu dizileri destekler.
- İki boyutlu dizi, satır ve sütunlarla tanımlanan tablo benzeri bir yapıdır: satranç tahtası, resim, not çizelgesi.
- Erişim:
matris[satir][sutun]; ilk indis satır, ikincisi sütun.
int[][] matris = new int[3][3]; // 3x3 boyutunda bir matris matris[1][2] = 6; // 2. satır, 3. sütun
Çok Boyutlu Diziler
İlk Değer Verme ve Diziler Dizisi
- İki boyutlu dizilere de ilklendirici listesiyle başlangıç değerleri atanabilir; boyut belirtmeye gerek yoktur.
- Java'da 2B dizi aslında dizilerin dizisidir:
matris[i]i. satırın kendisi, yani birint[]'dir. matris.length= satır sayısı,matris[0].length= ilk satırın sütun sayısı.
int[][] matris = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };
System.out.println(matris.length + " "
+ matris[0].length + " " + matris[1][2]);Çıktı
3 3 6
Çok Boyutlu Diziler
Düzensiz (Ragged) Diziler
int[][] ucgen = new int[3][]; for (int i = 0; i < ucgen.length; i++) { ucgen[i] = new int[i + 1]; } System.out.println(ucgen[0].length + " " + ucgen[1].length + " " + ucgen[2].length); int[][] tablo = {{1, 2}, {3, 4, 5}}; for (int[] satir : tablo) { for (int x : satir) { System.out.print(x + " "); } System.out.println(); }
Çıktı
1 2 3 1 2 3 4 5
- Satırlar ayrı diziler olduğu için uzunlukları farklı olabilir.
new int[3][]yalnızca satır referanslarını oluşturur (hepsinull); satırlar sonra ayrılır.- Bu yüzden iç döngüde
matris[i].lengthkullanmak, sabit sütun sayısından daha güvenlidir. for-eachile: dış döngü öğesi birint[]satırdır.
Çok Boyutlu Diziler · Adım adım kod izleme
Pascal Üçgeni: Satır Satır Düzensiz Dizi
new int[4][] yalnızca 4 satır referansı ayırır; hepsi null.
i = 0: 1 hücreli satır oluşur (0 ile dolu), p[0] onu gösterir.
Satırın ilk ve son hücresi aynı hücre: 1.
i = 1: 2 hücreli satır.
Uçlar 1; iç hücre yok (j < 1 hemen yanlış).
i = 2: 3 hücreli satır.
Uçlar 1.
p[2][1] = p[1][0] + p[1][1] = 1 + 1 = 2.
i = 3: 4 hücreli satır.
Uçlar 1.
p[3][1] = p[2][0] + p[2][1] = 1 + 2 = 3.
p[3][2] = p[2][1] + p[2][2] = 2 + 1 = 3.
Satırların uzunlukları 1, 2, 3, 4: düzensiz dizi. Son satır [1, 3, 3, 1] yazılır.
int[][] p = new int[4][]; for (int i = 0; i < p.length; i++) { p[i] = new int[i + 1]; p[i][0] = 1; p[i][i] = 1; for (int j = 1; j < i; j++) { p[i][j] = p[i - 1][j - 1] + p[i - 1][j]; } } System.out.println(Arrays.toString(p[3]));
Çok Boyutlu Diziler
Örnek: CokBoyutluDiziOrnegi
public class CokBoyutluDiziOrnegi { public static void main(String[] args) { // 3x3 boyutunda iki boyutlu bir dizi (matris) int[][] matris = new int[3][3]; // Matrisin elemanlarına ilk değerlerini atama for (int satir = 0; satir < 3; satir++) { for (int sutun = 0; sutun < 3; sutun++) { matris[satir][sutun] = satir * 3 + sutun + 1; } } // Matrisi ekrana yazdırma System.out.println("Matrisin Icerigi:"); for (int satir = 0; satir < 3; satir++) { for (int sutun = 0; sutun < 3; sutun++) { System.out.print(matris[satir][sutun] + " "); } System.out.println(); // Yeni satıra geçme } } }
Çıktı
Matrisin Icerigi: 1 2 3 4 5 6 7 8 9
satir * 3 + sutun + 1 hücreleri 1'den 9'a numaralar.Çok Boyutlu Diziler · Adım adım kod izleme
Matris Doldurma ve Yazdırma: Adım Adım
new int[3][3]: 3 satır × 3 sütun, tüm hücreler 0.
matris[0][0] = 0 * 3 + 0 + 1 = 1
matris[0][1] = 0 * 3 + 1 + 1 = 2
matris[0][2] = 0 * 3 + 2 + 1 = 3
matris[1][0] = 1 * 3 + 0 + 1 = 4. İç döngü bitti; dış döngü bir sonraki satıra geçti.
matris[1][1] = 1 * 3 + 1 + 1 = 5
matris[1][2] = 1 * 3 + 2 + 1 = 6
matris[2][0] = 2 * 3 + 0 + 1 = 7. İç döngü bitti; dış döngü bir sonraki satıra geçti.
matris[2][1] = 2 * 3 + 1 + 1 = 8
matris[2][2] = 2 * 3 + 2 + 1 = 9
Yazdırma döngüsü aynı sırayla gezinir; her satırın sonunda println() alt satıra geçer.
int[][] matris = new int[3][3]; for (int satir = 0; satir < 3; satir++) { for (int sutun = 0; sutun < 3; sutun++) { matris[satir][sutun] = satir * 3 + sutun + 1; } } System.out.println("Matrisin Icerigi:"); for (int satir = 0; satir < 3; satir++) { for (int sutun = 0; sutun < 3; sutun++) { System.out.print(matris[satir][sutun] + " "); } System.out.println(); }
Çok Boyutlu Diziler
Üç ve Daha Fazla Boyut
- Java'da üç boyutlu ve daha fazla boyutlu diziler de kullanılabilir: her ek boyut bir köşeli parantez daha demektir.
- Daha fazla boyut daha karmaşık veri yapılarına izin verir: bina
[kat][satir][sutun], renkli resim[y][x][kanal], zamanla değişen ölçüm tablosu. - Öğe sayısı boyutların çarpımıdır:
new int[3][3][3]→ 3 × 3 × 3 = 27 hücre. Boyut sayısı arttıkça bellek hızla büyür.
// 3x3x3 boyutunda üç boyutlu dizi int[][][] ucBoyutluDizi = new int[3][3][3]; ucBoyutluDizi[1][2][0] = 16; // katman 1, satır 2, sütun 0
Üç boyutlu dizi: 3 katman, her katman 3×3 bir matris
Çok Boyutlu Diziler
Örnek: UcBoyutluDiziOrnegi
int[][][] ucBoyutluDizi = new int[3][3][3]; for (int x = 0; x < 3; x++) { for (int y = 0; y < 3; y++) { for (int z = 0; z < 3; z++) { ucBoyutluDizi[x][y][z] = x * 9 + y * 3 + z + 1; } } } System.out.println("Uc Boyutlu Dizinin Icerigi:"); for (int x = 0; x < 3; x++) { for (int y = 0; y < 3; y++) { for (int z = 0; z < 3; z++) { System.out.print(ucBoyutluDizi[x][y][z] + " "); } System.out.println(); } System.out.println(); }
Çıktı
Uc Boyutlu Dizinin Icerigi: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
Üç iç içe döngü: z bir satırda, y bir katmanda, x tüm dizide gezinir. Her katmandan sonra boş satır basılır.
Çok Boyutlu Diziler
Matris Transpozu
public static void main(String[] args) { int[][] matris = { {1, 2, 3}, {4, 5, 6} }; System.out.println("Orijinal Matris:"); yazdirMatris(matris); int satirSayisi = matris.length; int sutunSayisi = matris[0].length; int[][] transpozMatris = new int[sutunSayisi][satirSayisi]; for (int i = 0; i < satirSayisi; i++) { for (int j = 0; j < sutunSayisi; j++) { transpozMatris[j][i] = matris[i][j]; } } System.out.println("Transpoz Matris:"); yazdirMatris(transpozMatris); }
Çıktı
Orijinal Matris: 1 2 3 4 5 6 Transpoz Matris: 1 4 2 5 3 6
- Transpoz, matrisin satırlarını sütunlara, sütunlarını satırlara dönüştürür:
T[j][i] = M[i][j]. - 2×3 matrisin transpozu 3×2'dir:
new int[sutunSayisi][satirSayisi].
Çok Boyutlu Diziler · Adım adım kod izleme
Transpoz: Hücre Hücre Kopyalama
satirSayisi = 2, sutunSayisi = 3; transpoz için 3×2'lik yeni bir dizi oluşturulur (hücreler 0).
transpozMatris[0][0] = matris[0][0] = 1 · matrisin satırı, transpozun sütunu oluyor.
transpozMatris[1][0] = matris[0][1] = 2
transpozMatris[2][0] = matris[0][2] = 3
transpozMatris[0][1] = matris[1][0] = 4 · matrisin satırı, transpozun sütunu oluyor.
transpozMatris[1][1] = matris[1][1] = 5
transpozMatris[2][1] = matris[1][2] = 6
for (int i = 0; i < satirSayisi; i++) { for (int j = 0; j < sutunSayisi; j++) { transpozMatris[j][i] = matris[i][j]; } }
Çok Boyutlu Diziler
Yardımcı Metot: yazdirMatris
public static void yazdirMatris(int[][] matris) { 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(); } }
- Yazdırma işi bir yardımcı metoda taşınmıştır;
mainiki kez çağırır: önce asıl matris, sonra transpoz. - Parametre
int[][] matris: her boyuttaki 2B diziyle çalışır, çünkü satır sayısımatris.length, sütun sayısımatris[i].lengthile diziden okunur. - Metoda dizinin kopyası değil referansı gider; büyük bir matris için bile çağrı ucuzdur.
- Sabit
3yazılsaydı 2×3 ve 3×2 matrislerden biri hatalı yazdırılır ya daArrayIndexOutOfBoundsExceptionoluşurdu.
Uygulama: Tic Tac Toe
Tic Tac Toe (X-O Oyunu)
- 3×3'lük bir oyun tahtası kullanılır:
char[][] tahta = new char[3][3]; - İki oyuncu (X ve O) sırayla hamle yapar; her hamle tek bir atamadır:
tahta[satir][sutun] = oyuncu. - Kendi işaretinden 3 tanesini aynı satıra, sütuna ya da çapraza yerleştiren oyunu kazanır.
- Boş hücre kalmazsa oyun berabere biter.
Sağdaki tahtada her tıklamada çalışan dizi ataması gösterilir.
Uygulama: Tic Tac Toe
TicTacToe: main
import java.util.Scanner; public class TicTacToe { static Scanner scanner = new Scanner(System.in); public static void main(String[] args) { char[][] tahta = new char[3][3]; // 3x3'lük tahta char oyuncu = 'X'; // İlk oyuncu X boolean oyunDevamEdiyor = true; tahtaDoldur(tahta); // Tüm hücreler boş while (oyunDevamEdiyor) { tahtayiGoster(tahta); hamleYap(tahta, oyuncu); oyunDevamEdiyor = oyunDevamEdiyorMu(tahta, oyuncu); // Oyuncu değişimi oyuncu = (oyuncu == 'X') ? 'O' : 'X'; } tahtayiGoster(tahta); } // ... metotlar }
- İş metotlara bölünmüştür: doldur, göster, hamle al, kontrol et.
- Tahta metotlara referansla gider:
hamleYap'ın yaptığı değişiklikmain'de görünür. - Metotlar
staticolmalıdır; değilse:
error: non-static method tahtaDoldur(char[][]) cannot be referenced from a static context
Uygulama: Tic Tac Toe
TicTacToe: Tahtayı Doldur ve Göster
public static void tahtaDoldur(char[][] tahta) { for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { tahta[i][j] = ' '; } } } public static void tahtayiGoster(char[][] tahta) { System.out.println("-------------"); for (int i = 0; i < 3; i++) { System.out.print("| "); for (int j = 0; j < 3; j++) { System.out.print(tahta[i][j] + " | "); } System.out.println("\n-------------"); } }
Boş tahtanın görünümü
------------- | | | | ------------- | | | | ------------- | | | | -------------
new char[3][3]hücreleri'\u0000'ile başlar; ekranda düzgün görünmesi ve boş hücre kontrolü için önce' '(boşluk) ile doldurulur."\n-------------": satır sonu ve ayırıcı çizgi tekprintlnile.
Uygulama: Tic Tac Toe
TicTacToe: Hamle Alma
static Scanner scanner = new Scanner(System.in); public static void hamleYap(char[][] tahta, char oyuncu) { int satir, sutun; do { System.out.print("Sıra " + oyuncu + " oyuncusunda. Satır ve sütun seçin (1-3): "); satir = scanner.nextInt() - 1; sutun = scanner.nextInt() - 1; } while (satir < 0 || satir > 2 || sutun < 0 || sutun > 2 || tahta[satir][sutun] != ' '); tahta[satir][sutun] = oyuncu; }
- 1 ile 0–2 indisine çevrilir.tahta[satir][sutun]'dan önce yazılır: || ilk doğru koşulda durduğu için sınır dışı erişim olmaz.Uygulama: Tic Tac Toe
TicTacToe: Kazanan Var mı?
public static boolean oyunDevamEdiyorMu(char[][] tahta, char oyuncu) { // Kazanan durumlarını kontrol et if ((tahta[0][0] == oyuncu && tahta[0][1] == oyuncu && tahta[0][2] == oyuncu) || (tahta[1][0] == oyuncu && tahta[1][1] == oyuncu && tahta[1][2] == oyuncu) || (tahta[2][0] == oyuncu && tahta[2][1] == oyuncu && tahta[2][2] == oyuncu) || (tahta[0][0] == oyuncu && tahta[1][0] == oyuncu && tahta[2][0] == oyuncu) || (tahta[0][1] == oyuncu && tahta[1][1] == oyuncu && tahta[2][1] == oyuncu) || (tahta[0][2] == oyuncu && tahta[1][2] == oyuncu && tahta[2][2] == oyuncu) || (tahta[0][0] == oyuncu && tahta[1][1] == oyuncu && tahta[2][2] == oyuncu) || (tahta[0][2] == oyuncu && tahta[1][1] == oyuncu && tahta[2][0] == oyuncu)) { System.out.println("Tebrikler, " + oyuncu + " oyuncusu kazandı!"); return false; } // ... berabere kontrolü
- 8 kazanma çizgisi tek tek denetlenir: her biri 3 hücrenin de
oyuncuolmasını ister (&&), çizgilerden biri yeterlidir (||). - Yalnızca son hamleyi yapan oyuncu denetlenir: yeni bir çizgiyi ancak o tamamlamış olabilir.
- Kazanan varsa metot
falsedöndürür: "oyun devam etmiyor".
Uygulama: Tic Tac Toe
TicTacToe: Berabere mi?
// oyunDevamEdiyorMu metodunun devamı // Berabere durumunu kontrol et boolean berabere = true; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (tahta[i][j] == ' ') { berabere = false; break; } } if (!berabere) { break; } } if (berabere) { System.out.println("Oyun berabere bitti."); return false; } return true;
- Önce oyunun berabere olduğu varsayılır (
berabere = true); tek bir boş hücre bu varsayımı çürütür. - İç
breakyalnızca iç döngüden çıkar; dıştakiif (!berabere) break;dış döngüyü de bitirir. - Kazanan yoksa ve boş hücre varsa
true: oyun devam eder. - Önce kazanma, sonra beraberlik denetlenir: son hamle tahtayı doldurup aynı anda kazandırabilir.
Uygulama: Tic Tac Toe · Adım adım kod izleme
Beraberlik: İki break, İki Döngü
Tahta: X O X · O X ␣ · O X O (␣: boşluk karakteri)
Önce beraberlik varsayılır. Tahtada tek boş hücre var: (1, 2).
(0, 0) = 'X': boş değil, devam.
(0, 1) = 'O': boş değil.
(0, 2) = 'X': satır 0 dolu; iç döngü kendiliğinden biter.
!berabere yanlış: dış döngü sürer.
i = 1: (1, 0) = 'O'.
(1, 1) = 'X'.
(1, 2) = ' ': boş hücre bulundu.
Varsayım çürüdü: berabere = false.
İç break: yalnızca iç döngüden çıkar; dış döngü hâlâ çalışıyor.
!berabere doğru.
Dış break: satır 2 hiç denetlenmez.
Boş hücre var: devam yazılır.
boolean berabere = true; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (tahta[i][j] == ' ') { berabere = false; break; } } if (!berabere) { break; } } System.out.println(berabere ? "berabere" : "devam");
Uygulama: Tic Tac Toe
Örnek Oyun
X 1 1 girer → tahta[0][0] = 'X'. Kazanan yok, boş hücre var → true; sıra O'ya geçer.
O 1 2 girer → tahta[0][1] = 'O'. Kazanan yok, boş hücre var → true; sıra X'e geçer.
X 2 2 girer → tahta[1][1] = 'X'. Kazanan yok, boş hücre var → true; sıra O'ya geçer.
O 2 2 girer: tahta[1][1] dolu (!= ' ') → do-while koşulu doğru, aynı soru tekrar sorulur.
O 1 3 girer → tahta[0][2] = 'O'. Kazanan yok, boş hücre var → true; sıra X'e geçer.
X 3 3 girer → tahta[2][2] = 'X'. Ana çapraz X → kazanma mesajı, oyunDevamEdiyorMu false döner, döngü biter.
Girdiler (satır sütun)
1 1 1 2 2 2 2 2 1 3 3 3
Programın son çıktısı
Tebrikler, X oyuncusu kazandı! ------------- | X | O | O | ------------- | | X | | ------------- | | | X | -------------
Özet
Özet
| Konu | Özü |
|---|---|
| Dizi | Aynı tipten, sabit sayıda öğe; indis 0 … length − 1 |
| Oluşturma | new int[n] (varsayılan değerler) · {1, 2, 3} (yalnızca tanımlamada) · new int[]{…} |
| length | Özellik, parantezsiz: dizi.length; 2B'de m.length satır, m[i].length sütun |
| Referans | Değişken adres tutar; b = a aynı dizi, clone()/Arrays.copyOf yeni dizi; == adres karşılaştırır |
| Bellek | Tüm diziler heap'te; referans yığında; erişilemeyen diziyi çöp toplayıcı temizler |
| Hata | Sınır dışı indis → ArrayIndexOutOfBoundsException; döngüde i < length |
| Algoritmalar | Erişim O(1) · ikili arama O(log n) · doğrusal arama, ters çevirme O(n) · eşleştirme, seçimli ve kabarcık sıralaması O(n²) |
| Çok boyut | Dizilerin dizisi; iç içe döngüler; satırlar farklı uzunlukta olabilir |
Özet
Sık Yapılan Hatalar (1)
a = {1, 2, 3};error: illegal start of expression → a = new int[]{1, 2, 3};length() yazmaka.length()error: cannot find symbol … method length() → a.lengthnew int[]error: array dimension missingint[] a = {1, 2.5, 3};error: incompatible types: possible lossy conversion from double to interror: cannot find symbol … variable ortancastatic olmayan metoterror: non-static method … cannot be referenced from a static contextÖzet
Sık Yapılan Hatalar (2)
a[a.length] ya da i <= a.length: ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3int[] a = null; a[0]: NullPointerException: Cannot load from int array because "a" is nullSystem.out.println(a) → [I@7ef20235. İçerik için Arrays.toString(a).b = a sonrası b[0]'ı değiştirmek a[0]'ı da değiştirir. Kopya: a.clone().== ile içerik karşılaştırmakAynı öğeli iki dizi için false. İçerik için Arrays.equals(a, b).dizi[0]'dır: (i + 1) + ". eleman".Özet
Örnek Problemler (1)
static int gizem(int[] d) { int s = 0; for (int i = 0; i < d.length; i += 2) { s += d[i]; } return s; } static void degistir(int[] d, int x) { d[0] = 100; x = 100; } // main: int[] d = {4, 8, 15, 16, 23, 42}; int[] a = {1, 2, 3}; int x = 1; degistir(a, x);
gizem(d)ne döndürür? Metot ne hesaplar?d[d.length / 2]kaçtır?degistir(a, x)sonrasıa[0]vexkaçtır? Neden farklılar?
Cevapları göster
- 42: çift indisli öğelerin toplamı 4 + 15 + 23.
- 6 / 2 = 3 →
d[3]= 16. - 100 1: dizi referansla gelir, hücresi değişir;
xbir kopyadır, asıl değişken 1 kalır.
Özet
Örnek Problemler (2)
int[][] m = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; int iz = 0; for (int i = 0; i < m.length; i++) { iz += m[i][i]; } // --- int[] b = new int[5]; for (int i = 1; i < b.length; i++) { b[i] = b[i - 1] + i; } System.out.println(Arrays.toString(b)); // --- int[] p = {3, 1, 2}; int[] q = p; q[2] = q[0] + q[1]; System.out.println(Arrays.toString(p));
- Birinci parçadaki
izkaçtır? Hangi hücreler toplanır? - İkinci parça ne yazdırır?
- Üçüncü parça ne yazdırır?
Cevapları göster
- 15: köşegen
m[0][0] + m[1][1] + m[2][2]= 1 + 5 + 9 (matrisin izi). - [0, 1, 3, 6, 10]: her hücre bir öncekine indisini ekler (0, 0+1, 1+2, 3+3, 6+4).
- [3, 1, 4]:
qvepaynı dizidir;q[2] = 3 + 1yazılıncapde değişir.
Özet
Alıştırmalar
int enBuyuk(int[] dizi): en büyük öğeyi döndürün.{12, 7, 30, 5, 18}→ ?int ciftSay(int[] dizi): çift öğelerin sayısını döndürün (for-each ile). Aynı dizi → ?int indisBul(int[] dizi, int hedef): hedefin indisini, yoksa −1 döndürün. 5 ve 99 için → ?int[][] topla(int[][] a, int[][] b): iki matrisin toplamı.{{1, 2}, {3, 4}}+{{5, 6}, {7, 8}}→ ?int[] satirToplamlari(int[][] m): her satırın toplamı.{{1, 2, 3}, {4, 5, 6}}→ ?- Tic Tac Toe'ya
tahtaDoluMumetodu ekleyip beraberlik kontrolünü onunla yazın.
Cevaplar / ipuçları
enb = dizi[0]ile başlayıpi = 1'den tarayın → 30. (0 ile başlamak negatif dizilerde yanlış sonuç verir.)if (x % 2 == 0) sayac++;→ 3 (12, 30, 18).- Klasik
forgerekir (indis lazım) → 3 ve −1. c[i][j] = a[i][j] + b[i][j]→ [[6, 8], [10, 12]].t[i] += m[i][j]→ [6, 15].- İki döngüyle
' 'arayın; buluncareturn false, döngü bitersereturn true.
Özet
Kaynaklar
- Oracle, The Java Tutorials: Arrays; The for Statement (enhanced for).
- Oracle, Java SE 21 API:
java.util.Arrays. - J. Gosling ve diğ., The Java Language Specification, Java SE 21 Edition (Bölüm 10: Arrays).
- P. Deitel ve H. Deitel, Java: How to Program, 11. baskı, Pearson (Bölüm 7: Arrays and ArrayLists).
- K. Sierra ve B. Bates, Head First Java, 3. baskı, O'Reilly.
- C. S. Horstmann, Core Java, Volume I: Fundamentals, 12. baskı, Pearson (3.10 Arrays).
- A. Downey ve C. Mayfield, Think Java, 2. baskı, O'Reilly (Bölüm 7: Arrays and References).