Bölüm 7: Ağaçlar

Veri Yapıları
Ağaç terimleriİkili ağaçlarDolu · tam · mükemmel Dizi ve bağlı gösterimGezinmelerÖzyineleme ve yığınB-ağacı ve B+ ağacı
Sercan KÜLCÜ · Giresun Üniversitesi · Bilgisayar Mühendisliği

Giriş

Öğrenme Çıktıları

Temel kavramlar

Kök, ebeveyn, çocuk, yaprak, derinlik ve yükseklik terimlerini açıklamak.

Gösterimler

Ağaçları düğüm bağlantıları ve dizilerle temsil etmek.

Gezinmeler

Kök önce, kök ortada, kök sonda ve seviye sıralı gezinmeyi uygulamak.

Uygulama ve maliyet

Ağaç türlerini kullanım alanları ve işlem maliyetleriyle karşılaştırmak.

Ağaç Kavramı

Ağaç (Tree)

  • Doğrusal olmayan, hiyerarşik bir veri yapısıdır.
  • Düğümler (node) ve onları bağlayan kenarlardan (edge) oluşur.
  • En üstte tek bir kök (root) bulunur; ağaç kökten aşağı doğru ters çizilir.
  • Kök dışındaki her düğümün tam bir ebeveyni vardır; bu yüzden döngü yoktur.
  • Her düğümün sıfır veya daha fazla çocuğu olabilir.
kökyapraklarkenar
Kural: n düğümlü bir ağaçta her zaman n − 1 kenar vardır (kök hariç her düğüm, ebeveynine tek bir kenarla bağlanır).

Ağaç Kavramı

Günlük Hayatta Ağaçlar: Hiyerarşi

/etcbinhomevarhostsnetworkaliaysenotlar.txtodevfoto.jpg
Dosya sistemiKök dizin, klasörler (iç düğüm), dosyalar (yaprak).
KitapKitap → kısımlar → bölümler → alt başlıklar.
CoğrafyaKıta → ülke → eyalet/il → şehir.
Web sayfasıHTML belgesi iç içe öğelerden oluşan bir ağaçtır (DOM).

Ağaç Kavramı

Ağaç mı?

AHGFBCEDJIKPLMNO

Bu yapı bir ağaç mıdır? 16 düğüm var; kenarları sayın ve döngü arayın.

AHGFBCEDJIKPLMNOIDJKMEPNOHLAGBFC

Evet. Bağlantılı, döngüsüz ve 16 düğüme 15 kenar. Herhangi bir düğüm (ör. I) kök seçilip ağaç olarak çizilebilir.

döngü variki ebeveynbağlantısız

Ağaç olmayanlar: döngü içeren, bir düğümü iki ebeveynli olan veya parçaları bağlantısız yapılar.

Ağaç Kavramı

Temel Unsurlar: Kök, İç Düğüm, Yaprak

Kök düğüm (root)Ağacın en üst düğümü; ebeveyni yoktur.dosya sistemi: kök dizin /
İç düğüm (internal node)En az bir çocuğu olan düğüm.dosya sistemi: klasörler
Yaprak (leaf)Hiç çocuğu olmayan düğüm; dış düğüm de denir.dosya sistemi: dosyalar
12934567kökiç düğümyapraklar: 9, 4, 5, 6, 7

Kök de (çocuğu varsa) bir iç düğümdür. Tek düğümlü ağaçta kök aynı zamanda yapraktır.

Ağaç Kavramı

Ağaç İlişkileri

TerimAnlamı (sağdaki ağaçta)
Ebeveyn (parent)Hemen üstteki düğüm: D, H'nin ebeveyni
Çocuk (child)Hemen alttaki düğüm: H, I, J → D'nin çocukları
Kardeş (sibling)Ebeveyni aynı olanlar: H, I, J
Ata (ancestor)Köke giden yoldaki düğümler: M'nin ataları H, D, A
Soy (descendant)Alt ağaçtaki düğümler: D'nin soyu H, I, J, M
ABCDEFGHIJKLM
Dikkat: Aynı düzeyde olmak kardeş olmak demek değildir. F ve G aynı derinlikte ama ebeveynleri farklı (B ve C) → kardeş değiller.

Ağaç Kavramı

Terimler Ağaç Üzerinde

d=0d=1d=2d=3ABCDEFGHIJKLM

Kök: ebeveyni olmayan tek düğüm → A.

d=0d=1d=2d=3ABCDEFGHIJKLM

Ebeveyn / çocuk: D, H, I ve J'nin ebeveynidir; H, I, J de D'nin çocuklarıdır.

d=0d=1d=2d=3ABCDEFGHIJKLM

Kardeşler: H, I, J (ebeveynleri D). F ile G kardeş değildir.

d=0d=1d=2d=3ABCDEFGHIJKLM

Yapraklar: K, L, F, G, M, I, J (çocuksuz düğümler).

d=0d=1d=2d=3ABCDEFGHIJKLM

İç düğümler: A, B, C, D, E, H (en az bir çocuğu olanlar).

d=0d=1d=2d=3ABCDEFGHIJKLM

Atalar: M'nin ataları H, D, A. Tersine M; H, D ve A'nın soyundandır.

d=0d=1d=2d=3ABCDEFGHIJKLM321321

Derece (degree) = çocuk sayısı: A 3, B 2, C 1, D 3 … Ağacın derecesi = en büyük derece = 3.

d=0d=1d=2d=3ABCDEFGHIJKLM

Derinlik (depth): kökten düğüme kenar sayısı. E'nin derinliği 2 (A→B→E).

d=0d=1d=2d=3ABCDEFGHIJKLM

Yükseklik (height): kökten en uzak yaprağa kenar sayısı = 3 (A→B→E→K).

d=0d=1d=2d=3ABCDEFGHIJKLM

Alt ağaç (subtree): D ve tüm soyu (H, I, J, M) kendi başına bir ağaçtır.

Ağaç Kavramı

Derece, Derinlik, Yükseklik

ÖlçüTanımÖnceki ağaçta
Derece (degree)Bir düğümün çocuk sayısı (alt ağaç sayısı)D → 3
Derinlik (depth)Kökten o düğüme kadar olan yoldaki kenar sayısı; kökün derinliği 0E → 2
Düzey (level)Aynı derinlikteki düğümlerin kümesidüzey 2: E … J
Düğüm yüksekliğiDüğümden altındaki en uzak yaprağa kenar sayısı; yaprağın yüksekliği 0D → 2
Ağacın yüksekliğiKökün yüksekliği = en büyük derinlik3
Bu derste yükseklik ve derinlik kenar sayısı ile ölçülür. Bazı kaynaklar düğüm sayısını kullanır (düzeyleri 1'den başlatır); o zaman tüm değerler 1 fazla çıkar. Hangi tanımın kullanıldığına dikkat edin.

Ağaç Kavramı

Derinlik ve Yükseklik

ABCDEFGHIJK
Ağacın yüksekliği = kökün yüksekliği = 3 (en uzun yol A→E→J→K). En derin düğüm K'nin derinliği de 3'tür.
DüğümYükseklikDerinlik
A30
B11
C01
D11
E21
F02
G02
H02
I02
J12
K03

Ağaç Kavramı

Yol ve Alt Ağaç

  • Yol (path): ardışık düğümleri kenarlarla bağlayan dizi.
    p = (v₀, e₁, v₁, …, ek, vk)
  • start(p) = v₀, end(p) = vk, length(p) = k (kenar sayısı).
  • Ağaçta iki düğüm arasında tam bir yol vardır (döngü olmadığı için).
  • Alt ağaç (subtree): bir düğüm ve onun tüm soyu; kendisi de bir ağaçtır. Ör. bir klasör ve altındaki her şey.
ABCDEFGHIJKLM
Vurgulu yol: K → E → B → A → D → H → M, uzunluğu 6. Bu iki düğüm arasında başka yol yoktur.

Ağaç Kavramı

Temel Ağaç Türleri

TürÖzellik
Genel ağaçBir düğümün çocuk sayısına sınır yoktur.
k-lı ağaç (k-ary)Her düğümün en fazla k çocuğu vardır.
İkili ağaç (binary)Her düğümün en fazla iki çocuğu vardır: sol ve sağ.
İkili arama ağacı (BST)İkili ağaç + her düğümde: sol alt ağaçtaki anahtarlar küçük, sağdakiler büyük.

Dengeli arama ağaçları Bölüm 10'da; çok yollu ağaçlar bu bölümün sonunda ele alınır.

İkili Ağaçlar

İkili Ağaç (Binary Tree)

  • Her düğümün en fazla iki çocuğu vardır: sol çocuk ve sağ çocuk.
  • Çocukların yeri önemlidir: yalnızca sol çocuğu olan ağaç, yalnızca sağ çocuğu olandan farklıdır.
  • Özyinelemeli tanım: İkili ağaç ya boştur ya da bir kök ile iki ikili ağaçtan (sol ve sağ alt ağaç) oluşur.
ABAB≠
ABCDABCDEFGHIJK

Soldaki zincir de geçerli bir ikili ağaçtır (çarpık / skewed ağaç): düğümler dengeli dağılmak zorunda değildir.

İkili Ağaçlar

Dolu, Tam ve Mükemmel

Dolu ikili ağaç (full)Her düğümün ya 0 ya da 2 çocuğu vardır; tek çocuklu düğüm yoktur.
Tam ikili ağaç (complete)Son düzey hariç tüm düzeyler doludur; son düzey soldan sağa boşluksuz dolar.
Mükemmel ikili ağaç (perfect)Tüm iç düğümlerin 2 çocuğu var ve tüm yapraklar aynı derinlikte.
Mükemmel ağaç hem dolu hem tamdır; yüksekliği h ise 2h+1 − 1 düğümü vardır. Türkçe kaynaklarda "tam" ve "dolu" bazen ters kullanılır; İngilizce karşılıklar (full / complete / perfect) esas alınmalıdır.

İkili Ağaçlar

Hangisi? Dolu mu, Tam mı, Mükemmel mi?

ABCDEHI
Dolu (full)evet
Tam (complete)hayır
Mükemmel (perfect)hayır

Her düğümün 0 ya da 2 çocuğu var → dolu. Ama C'nin altı boşken en alt düzey E'nin altında → tam değil.

12345678910
Dolu (full)hayır
Tam (complete)evet
Mükemmel (perfect)hayır

Son düzey (8, 9, 10) soldan sağa boşluksuz → tam. 5'in tek çocuğu (10) var → dolu değil.

12345678911
Dolu (full)hayır
Tam (complete)hayır
Mükemmel (perfect)hayır

5'in tek çocuğu var → dolu değil. 10. konum boşken 11 dolu → tam değil. Ne tam ne dolu.

1234567
Dolu (full)evet
Tam (complete)evet
Mükemmel (perfect)evet

Tüm iç düğümlerin 2 çocuğu var, tüm yapraklar aynı derinlikte → mükemmel (dolayısıyla dolu ve tam).

İkili Ağaçlar

İkili Ağaç Özellikleri

ÖzellikFormülÖrnek
d derinliğindeki en fazla düğüm2dd = 3 → en fazla 8 düğüm
Yüksekliği h olan ağaçta en fazla düğüm2h+1 − 1h = 3 → 15 (mükemmel ağaç)
Yüksekliği h olan ağaçta en az düğümh + 1çarpık (zincir) ağaç
n düğümlü ağacın yüksekliği⌊log2 n⌋ ≤ h ≤ n − 1n = 15 → 3 ≤ h ≤ 14
n düğümlü ağaçtaki kenar sayısın − 1her düğümün tek ebeveyni
Dolu ikili ağaçta yaprak sayısıiç düğüm + 17 düğüm → 3 iç, 4 yaprak
Yükseklik, ağaç işlemlerinin maliyetini belirler: dengeli bir ağaçta h ≈ log2 n (1 milyon düğüm → ≈ 20 düzey), çarpık ağaçta h = n − 1.

Gösterimler

Dizi Gösterimi

Düğümler düzey düzey, soldan sağa diziye yerleştirilir. Kök indis 1'de ise, indis i'deki düğüm için:

1 tabanlı0 tabanlı
Sol çocuk2i2i + 1
Sağ çocuk2i + 12i + 2
Ebeveyn⌊i / 2⌋⌊(i − 1) / 2⌋

Örnek: E (i = 5) → çocuklar 10 ve 11 (boş), ebeveyn ⌊5/2⌋ = 2 (B).

ABCDEFGHI1234567890A1B2C3D4E5F6G7H8I9

Referans tutulmaz; ebeveyn/çocuk erişimi O(1) aritmetikle yapılır. Tam ikili ağaçlar için idealdir (Bölüm 8: heap).

Gösterimler

Dizide Bellek İsrafı

ABCDE124816
  • Çarpık ağaçta düğümlerin indisleri katlanarak büyür: 1, 2, 4, 8, 16.
  • 5 düğüm için 16 hücre gerekir; 11 hücre boş kalır. Sağa çarpık olsaydı indisler 1, 3, 7, 15, 31 olurdu → 31 hücre.
  • Genel olarak n düğümlü bir ağaç 2n − 1 hücreye kadar yer isteyebilir.
A1B23C4567D89101112131415E16

Dizi gösterimi

  • Referans yok, hızlı indis hesabı
  • Tam ağaçlarda boşluksuz

Ama

  • Seyrek/çarpık ağaçta büyük israf
  • Boyut sabit; büyütmek için kopyalama

Gösterimler

Bağlı Gösterim (Linked Representation)

  • Her ağaç düğümü bir nesnedir: veri + sol ve sağ çocuk referansı.
  • Çocuk yoksa referans null'dır.
  • Boyut dinamiktir; yalnızca var olan düğümler için bellek ayrılır.
  • Bir düğüme ulaşmak için kökten başlayıp referansları izlemek gerekir.
solverisagsol alt ağaçsağ alt ağaç
public class AgacDugumu {
    int veri;
    AgacDugumu sol;   // sol çocuk (yoksa null)
    AgacDugumu sag;   // sağ çocuk (yoksa null)

    public AgacDugumu(int veri) {
        this.veri = veri;   // sol = sag = null
    }
}
// 9 kökünde küçük bir ağaç kuralım
AgacDugumu kok = new AgacDugumu(9);
kok.sol = new AgacDugumu(2);
kok.sag = new AgacDugumu(3);
kok.sol.sol = new AgacDugumu(4);

Gösterimler

Bağlı Gösterim: Örnek

ABCDEFGçapraz çizgi = null referans
7 düğüm14 referans alanı: 6'sı dolu (kenar sayısı n − 1), 8'i null.
Genel kuraln düğümlü ikili ağaçta her zaman n + 1 null referans vardır.
Ebeveyne çıkışGerekirse düğüme bir ebeveyn referansı da eklenir.

Gösterimler

Dizi mi, Bağlı mı?

ÖlçütDizi gösterimiBağlı gösterim
BellekTam ağaçta en az; seyrek ağaçta 2n − 1'e kadar israfDüğüm başına 2 ek referans; israf yok
Çocuk / ebeveyn erişimiO(1), indis aritmetiğiyleÇocuk O(1); ebeveyn için ek referans gerekir
i. düzeydeki k. düğümO(1): indis 2i + k − 1 (1 tabanlı, k ≥ 1)Kökten gezinme gerekir
BüyümeDizi dolunca kopyalanarak büyütülürYeni düğüm eklemek O(1) (konum biliniyorsa)
Uygun olduğu yerTam ikili ağaçlar (heap)Genel ve değişken şekilli ağaçlar (BST, ifade ağacı)
Kural: ağacın şekli tam kalıyorsa dizi, şekli öngörülemiyorsa bağlı gösterim tercih edilir.

Gösterimler

Genel Ağaç Gösterimi

Çocuk sayısı sınırsız olduğunda iki yaygın yol vardır:

// 1) Çocuk listesi
class GenelDugum {
    int veri;
    List<GenelDugum> cocuklar
        = new ArrayList<>();
}
// 2) İlk çocuk – sonraki kardeş
class KardesDugum {
    int veri;
    KardesDugum ilkCocuk;
    KardesDugum sonrakiKardes;
}

İkinci yolda her düğüm yine iki referans tutar: ilk çocuk (aşağı) ve sonraki kardeş (sağa). Böylece her genel ağaç bir ikili ağaç gibi saklanabilir.

ABCDEFGABCDEFG

Solda genel ağaç; sağda ilk çocuk (düz ok) – sonraki kardeş (kesikli ok) gösterimi.

Gezinmeler

Ağaç Gezinmeleri

Gezinme: Her düğümü bir kez ziyaret eder. DFS türleri kökün ziyaret zamanına göre; BFS ise düzeylere göre ilerler.
1234567
GezinmeSıraÇıktıTipik kullanım
Kök başta (preorder)kök → sol → sağ1 2 4 5 3 6 7Ağacı kopyalamak, önek ifade
Kök ortada (inorder)sol → kök → sağ4 2 5 1 6 3 7BST'yi sıralı dolaşmak
Kök sonda (postorder)sol → sağ → kök4 5 2 6 7 3 1Silme, boyut/yükseklik hesabı
Seviye sırası (level-order)düzey düzey, soldan sağa1 2 3 4 5 6 7Düzey bazlı işlemler

Gezinmeler

Kök Başta Gezinme (Preorder)

  1. Kökü ziyaret et.
  2. Sol alt ağacı kök başta gez.
  3. Sağ alt ağacı kök başta gez.

Kullanım: ağacı kopyalamak, düğümleri diziye yazmak, önek (prefix) ifade.

ziyaret(kok);
kokBasta(kok.sol);
kokBasta(kok.sag);
1234567Çıktı: 1şimdiziyaret edildibekliyor

Kök 1 ziyaret edilir; sonra sol alt ağaca geçilir.

1234567Çıktı: 1 2şimdiziyaret edildibekliyor

2 ziyaret edilir; sonra onun sol alt ağacı.

1234567Çıktı: 1 2 4şimdiziyaret edildibekliyor

4 yaprak: ziyaret edilir, çocuğu yok.

1234567Çıktı: 1 2 4 5şimdiziyaret edildibekliyor

2'nin sağ alt ağacı: 5.

1234567Çıktı: 1 2 4 5 3şimdiziyaret edildibekliyor

Sol alt ağaç bitti; 1'in sağ alt ağacı: 3.

1234567Çıktı: 1 2 4 5 3 6şimdiziyaret edildibekliyor

3'ün sol çocuğu 6.

1234567Çıktı: 1 2 4 5 3 6 7şimdiziyaret edildibekliyor

3'ün sağ çocuğu 7. Çıktı: 1 2 4 5 3 6 7

Gezinmeler

Kök Ortada Gezinme (Inorder)

  1. Sol alt ağacı kök ortada gez.
  2. Kökü ziyaret et.
  3. Sağ alt ağacı kök ortada gez.

Kullanım: ikili arama ağacında anahtarları küçükten büyüğe sıralı vermek, ara ek (infix) ifade.

kokOrtada(kok.sol);
ziyaret(kok);
kokOrtada(kok.sag);
1234567Çıktı: 4şimdiziyaret edildibekliyor

Kökten hep sola inilir; ilk ziyaret en soldaki düğüm: 4.

1234567Çıktı: 4 2şimdiziyaret edildibekliyor

4'ün alt ağacı bitti → ebeveyni 2.

1234567Çıktı: 4 2 5şimdiziyaret edildibekliyor

2'nin sağ alt ağacı: 5.

1234567Çıktı: 4 2 5 1şimdiziyaret edildibekliyor

Sol alt ağaç tamamlandı → kök 1.

1234567Çıktı: 4 2 5 1 6şimdiziyaret edildibekliyor

Sağ alt ağaçta yine en sola inilir: 6.

1234567Çıktı: 4 2 5 1 6 3şimdiziyaret edildibekliyor

6'dan sonra ebeveyni 3.

1234567Çıktı: 4 2 5 1 6 3 7şimdiziyaret edildibekliyor

Son olarak 7. Çıktı: 4 2 5 1 6 3 7

Gezinmeler

Kök Sonda Gezinme (Postorder)

  1. Sol alt ağacı kök sonda gez.
  2. Sağ alt ağacı kök sonda gez.
  3. Kökü ziyaret et.

Kullanım: ağacı silmek (önce çocuklar), boyut/yükseklik hesabı, sonek (postfix) ifade.

kokSonda(kok.sol);
kokSonda(kok.sag);
ziyaret(kok);
1234567Çıktı: 4şimdiziyaret edildibekliyor

En soldaki yaprak 4 ilk ziyaret edilir.

1234567Çıktı: 4 5şimdiziyaret edildibekliyor

Sonra 2'nin sağ çocuğu 5.

1234567Çıktı: 4 5 2şimdiziyaret edildibekliyor

2'nin iki alt ağacı da bitti → 2.

1234567Çıktı: 4 5 2 6şimdiziyaret edildibekliyor

1'in sağ alt ağacı: önce 6.

1234567Çıktı: 4 5 2 6 7şimdiziyaret edildibekliyor

Sonra 7.

1234567Çıktı: 4 5 2 6 7 3şimdiziyaret edildibekliyor

3'ün çocukları bitti → 3.

1234567Çıktı: 4 5 2 6 7 3 1şimdiziyaret edildibekliyor

Kök en son ziyaret edilir: 1. Çıktı: 4 5 2 6 7 3 1

Gezinmeler

Seviye Sırası Gezinme (Level-order)

  • Kökten başlar, her düzeyi soldan sağa tarar, sonra bir alt düzeye iner.
  • Genişlik öncelikli aramanın (BFS) ağaçtaki hâlidir.
  • Özyineleme yerine bir kuyruk (FIFO) kullanır: önce gelen düğümün çocukları önce işlenir.

Kullanım: düzey bazlı işlemler (her düzeyin toplamı, en yakın yaprak), ağacı düzey düzey yazdırmak.

düzey 0düzey 1düzey 21234567Çıktı: 1 2 3 4 5 6 7

Gezinmeler

Özyinelemeli Kök Başta ve Çağrı Yığını

nullnullnullnullnull9234Çıktı: 9
1public void kokBasta(AgacDugumu kok) {2  if (kok == null) {3    return;4  }5  System.out.print(kok.veri + " ");6  kokBasta(kok.sol);7  kokBasta(kok.sag);8}
Çağrı yığını (üst en üstte)Satır
kokBasta(9)5

kokBasta(9): kök null değil; 9 yazdırılır (satır 5).

nullnullnullnullnull9234Çıktı: 9 2
1public void kokBasta(AgacDugumu kok) {2  if (kok == null) {3    return;4  }5  System.out.print(kok.veri + " ");6  kokBasta(kok.sol);7  kokBasta(kok.sag);8}
Çağrı yığını (üst en üstte)Satır
kokBasta(2)5
kokBasta(9)6

Satır 6: kokBasta(9.sol) = kokBasta(2) yığına eklenir; 2 yazdırılır.

nullnullnullnullnull9234Çıktı: 9 2 4
1public void kokBasta(AgacDugumu kok) {2  if (kok == null) {3    return;4  }5  System.out.print(kok.veri + " ");6  kokBasta(kok.sol);7  kokBasta(kok.sag);8}
Çağrı yığını (üst en üstte)Satır
kokBasta(4)5
kokBasta(2)6
kokBasta(9)6

kokBasta(4) çağrılır; 4 yazdırılır.

nullnullnullnullnull9234Çıktı: 9 2 4
1public void kokBasta(AgacDugumu kok) {2  if (kok == null) {3    return;4  }5  System.out.print(kok.veri + " ");6  kokBasta(kok.sol);7  kokBasta(kok.sag);8}
Çağrı yığını (üst en üstte)Satır
kokBasta(null)3
kokBasta(4)6
kokBasta(2)6
kokBasta(9)6

kokBasta(4.sol) = kokBasta(null): satır 3'te hemen döner.

nullnullnullnullnull9234Çıktı: 9 2 4
1public void kokBasta(AgacDugumu kok) {2  if (kok == null) {3    return;4  }5  System.out.print(kok.veri + " ");6  kokBasta(kok.sol);7  kokBasta(kok.sag);8}
Çağrı yığını (üst en üstte)Satır
kokBasta(null)3
kokBasta(4)7
kokBasta(2)6
kokBasta(9)6

Satır 7: 4.sag de null; döner. Ardından kokBasta(4) biter.

nullnullnullnullnull9234Çıktı: 9 2 4
1public void kokBasta(AgacDugumu kok) {2  if (kok == null) {3    return;4  }5  System.out.print(kok.veri + " ");6  kokBasta(kok.sol);7  kokBasta(kok.sag);8}
Çağrı yığını (üst en üstte)Satır
kokBasta(null)3
kokBasta(2)7
kokBasta(9)6

2'ye dönüldü; satır 7: kokBasta(2.sag) = null → döner. kokBasta(2) biter.

nullnullnullnullnull9234Çıktı: 9 2 4 3
1public void kokBasta(AgacDugumu kok) {2  if (kok == null) {3    return;4  }5  System.out.print(kok.veri + " ");6  kokBasta(kok.sol);7  kokBasta(kok.sag);8}
Çağrı yığını (üst en üstte)Satır
kokBasta(3)5
kokBasta(9)7

9'a dönüldü; satır 7: kokBasta(3), 3 yazdırılır.

nullnullnullnullnull9234Çıktı: 9 2 4 3
1public void kokBasta(AgacDugumu kok) {2  if (kok == null) {3    return;4  }5  System.out.print(kok.veri + " ");6  kokBasta(kok.sol);7  kokBasta(kok.sag);8}
Çağrı yığını (üst en üstte)Satır
kokBasta(null)3
kokBasta(3)7
kokBasta(9)7

3'ün iki çocuğu da null; iki çağrı da hemen döner.

nullnullnullnullnull9234Çıktı: 9 2 4 3
1public void kokBasta(AgacDugumu kok) {2  if (kok == null) {3    return;4  }5  System.out.print(kok.veri + " ");6  kokBasta(kok.sol);7  kokBasta(kok.sag);8}
Çağrı yığını (üst en üstte)Satır
(boş)

kokBasta(3) ve kokBasta(9) biter; yığın boşalır. Çıktı: 9 2 4 3

Gezinmeler

Özyinelemeli Kök Ortada ve Çağrı Yığını

nullnullnullnullnull9234Çıktı: —
1public void kokOrtada(AgacDugumu kok) {2  if (kok == null) {3    return;4  }5  kokOrtada(kok.sol);6  System.out.print(kok.veri + " ");7  kokOrtada(kok.sag);8}
Çağrı yığını (üst en üstte)Satır
kokOrtada(9)5

kokOrtada(9): önce sol alt ağaç (satır 5); 9 henüz yazdırılmaz.

nullnullnullnullnull9234Çıktı: —
1public void kokOrtada(AgacDugumu kok) {2  if (kok == null) {3    return;4  }5  kokOrtada(kok.sol);6  System.out.print(kok.veri + " ");7  kokOrtada(kok.sag);8}
Çağrı yığını (üst en üstte)Satır
kokOrtada(2)5
kokOrtada(9)5

kokOrtada(2): yine önce sol alt ağaç.

nullnullnullnullnull9234Çıktı: —
1public void kokOrtada(AgacDugumu kok) {2  if (kok == null) {3    return;4  }5  kokOrtada(kok.sol);6  System.out.print(kok.veri + " ");7  kokOrtada(kok.sag);8}
Çağrı yığını (üst en üstte)Satır
kokOrtada(4)5
kokOrtada(2)5
kokOrtada(9)5

kokOrtada(4): sol alt ağaca inilir.

nullnullnullnullnull9234Çıktı: —
1public void kokOrtada(AgacDugumu kok) {2  if (kok == null) {3    return;4  }5  kokOrtada(kok.sol);6  System.out.print(kok.veri + " ");7  kokOrtada(kok.sag);8}
Çağrı yığını (üst en üstte)Satır
kokOrtada(null)3
kokOrtada(4)5
kokOrtada(2)5
kokOrtada(9)5

4.sol null → çağrı hemen döner.

nullnullnullnullnull9234Çıktı: 4
1public void kokOrtada(AgacDugumu kok) {2  if (kok == null) {3    return;4  }5  kokOrtada(kok.sol);6  System.out.print(kok.veri + " ");7  kokOrtada(kok.sag);8}
Çağrı yığını (üst en üstte)Satır
kokOrtada(4)6
kokOrtada(2)5
kokOrtada(9)5

Sol taraf bitti; 4 yazdırılır (satır 6).

nullnullnullnullnull9234Çıktı: 4
1public void kokOrtada(AgacDugumu kok) {2  if (kok == null) {3    return;4  }5  kokOrtada(kok.sol);6  System.out.print(kok.veri + " ");7  kokOrtada(kok.sag);8}
Çağrı yığını (üst en üstte)Satır
kokOrtada(null)3
kokOrtada(4)7
kokOrtada(2)5
kokOrtada(9)5

4.sag null → döner; kokOrtada(4) biter.

nullnullnullnullnull9234Çıktı: 4 2
1public void kokOrtada(AgacDugumu kok) {2  if (kok == null) {3    return;4  }5  kokOrtada(kok.sol);6  System.out.print(kok.veri + " ");7  kokOrtada(kok.sag);8}
Çağrı yığını (üst en üstte)Satır
kokOrtada(2)6
kokOrtada(9)5

2'ye dönüldü; 2 yazdırılır.

nullnullnullnullnull9234Çıktı: 4 2
1public void kokOrtada(AgacDugumu kok) {2  if (kok == null) {3    return;4  }5  kokOrtada(kok.sol);6  System.out.print(kok.veri + " ");7  kokOrtada(kok.sag);8}
Çağrı yığını (üst en üstte)Satır
kokOrtada(null)3
kokOrtada(2)7
kokOrtada(9)5

2.sag null → döner; kokOrtada(2) biter.

nullnullnullnullnull9234Çıktı: 4 2 9
1public void kokOrtada(AgacDugumu kok) {2  if (kok == null) {3    return;4  }5  kokOrtada(kok.sol);6  System.out.print(kok.veri + " ");7  kokOrtada(kok.sag);8}
Çağrı yığını (üst en üstte)Satır
kokOrtada(9)6

9'a dönüldü; sol alt ağaç bitti, 9 yazdırılır.

nullnullnullnullnull9234Çıktı: 4 2 9
1public void kokOrtada(AgacDugumu kok) {2  if (kok == null) {3    return;4  }5  kokOrtada(kok.sol);6  System.out.print(kok.veri + " ");7  kokOrtada(kok.sag);8}
Çağrı yığını (üst en üstte)Satır
kokOrtada(null)3
kokOrtada(3)5
kokOrtada(9)7

Satır 7: kokOrtada(3); 3.sol null → döner.

nullnullnullnullnull9234Çıktı: 4 2 9 3
1public void kokOrtada(AgacDugumu kok) {2  if (kok == null) {3    return;4  }5  kokOrtada(kok.sol);6  System.out.print(kok.veri + " ");7  kokOrtada(kok.sag);8}
Çağrı yığını (üst en üstte)Satır
kokOrtada(3)6
kokOrtada(9)7

3 yazdırılır.

nullnullnullnullnull9234Çıktı: 4 2 9 3
1public void kokOrtada(AgacDugumu kok) {2  if (kok == null) {3    return;4  }5  kokOrtada(kok.sol);6  System.out.print(kok.veri + " ");7  kokOrtada(kok.sag);8}
Çağrı yığını (üst en üstte)Satır
(boş)

3.sag null; kokOrtada(3) ve kokOrtada(9) biter. Çıktı: 4 2 9 3

Gezinmeler

Özyinelemeli Kök Sonda ve Çağrı Yığını

nullnullnullnullnull9234Çıktı: —
1public void kokSonda(AgacDugumu kok) {2  if (kok == null) {3    return;4  }5  kokSonda(kok.sol);6  kokSonda(kok.sag);7  System.out.print(kok.veri + " ");8}
Çağrı yığını (üst en üstte)Satır
kokSonda(9)5

kokSonda(9): önce sol alt ağaç.

nullnullnullnullnull9234Çıktı: —
1public void kokSonda(AgacDugumu kok) {2  if (kok == null) {3    return;4  }5  kokSonda(kok.sol);6  kokSonda(kok.sag);7  System.out.print(kok.veri + " ");8}
Çağrı yığını (üst en üstte)Satır
kokSonda(2)5
kokSonda(9)5

kokSonda(2): önce sol alt ağaç.

nullnullnullnullnull9234Çıktı: —
1public void kokSonda(AgacDugumu kok) {2  if (kok == null) {3    return;4  }5  kokSonda(kok.sol);6  kokSonda(kok.sag);7  System.out.print(kok.veri + " ");8}
Çağrı yığını (üst en üstte)Satır
kokSonda(4)5
kokSonda(2)5
kokSonda(9)5

kokSonda(4): önce sol alt ağaç.

nullnullnullnullnull9234Çıktı: —
1public void kokSonda(AgacDugumu kok) {2  if (kok == null) {3    return;4  }5  kokSonda(kok.sol);6  kokSonda(kok.sag);7  System.out.print(kok.veri + " ");8}
Çağrı yığını (üst en üstte)Satır
kokSonda(null)3
kokSonda(4)6
kokSonda(2)5
kokSonda(9)5

4'ün sol ve sağ çocuğu null: iki çağrı da hemen döner.

nullnullnullnullnull9234Çıktı: 4
1public void kokSonda(AgacDugumu kok) {2  if (kok == null) {3    return;4  }5  kokSonda(kok.sol);6  kokSonda(kok.sag);7  System.out.print(kok.veri + " ");8}
Çağrı yığını (üst en üstte)Satır
kokSonda(4)7
kokSonda(2)5
kokSonda(9)5

İki alt ağaç bitti; 4 yazdırılır (satır 7).

nullnullnullnullnull9234Çıktı: 4
1public void kokSonda(AgacDugumu kok) {2  if (kok == null) {3    return;4  }5  kokSonda(kok.sol);6  kokSonda(kok.sag);7  System.out.print(kok.veri + " ");8}
Çağrı yığını (üst en üstte)Satır
kokSonda(null)3
kokSonda(2)6
kokSonda(9)5

2'ye dönüldü; satır 6: 2.sag null → döner.

nullnullnullnullnull9234Çıktı: 4 2
1public void kokSonda(AgacDugumu kok) {2  if (kok == null) {3    return;4  }5  kokSonda(kok.sol);6  kokSonda(kok.sag);7  System.out.print(kok.veri + " ");8}
Çağrı yığını (üst en üstte)Satır
kokSonda(2)7
kokSonda(9)5

2'nin iki alt ağacı bitti; 2 yazdırılır.

nullnullnullnullnull9234Çıktı: 4 2
1public void kokSonda(AgacDugumu kok) {2  if (kok == null) {3    return;4  }5  kokSonda(kok.sol);6  kokSonda(kok.sag);7  System.out.print(kok.veri + " ");8}
Çağrı yığını (üst en üstte)Satır
kokSonda(3)5
kokSonda(9)6

9'a dönüldü; satır 6: kokSonda(3).

nullnullnullnullnull9234Çıktı: 4 2 3
1public void kokSonda(AgacDugumu kok) {2  if (kok == null) {3    return;4  }5  kokSonda(kok.sol);6  kokSonda(kok.sag);7  System.out.print(kok.veri + " ");8}
Çağrı yığını (üst en üstte)Satır
kokSonda(3)7
kokSonda(9)6

3'ün iki çocuğu da null; ardından 3 yazdırılır.

nullnullnullnullnull9234Çıktı: 4 2 3 9
1public void kokSonda(AgacDugumu kok) {2  if (kok == null) {3    return;4  }5  kokSonda(kok.sol);6  kokSonda(kok.sag);7  System.out.print(kok.veri + " ");8}
Çağrı yığını (üst en üstte)Satır
kokSonda(9)7

Kök en son: 9 yazdırılır, yığın boşalır. Çıktı: 4 2 3 9

Gezinmeler

Yığın ile Kök Başta Gezinme

1234567Yığın1üstÇıktı: —şimdiyapıdayazdırıldı
public void kokBastaYigin(AgacDugumu kok) {    if (kok == null) return;    Stack<AgacDugumu> yigit = new Stack<>();    yigit.push(kok);    while (!yigit.isEmpty()) {        AgacDugumu gecici = yigit.pop();        System.out.print(gecici.veri + " ");        if (gecici.sag != null)            yigit.push(gecici.sag);  // önce sağ        if (gecici.sol != null)            yigit.push(gecici.sol);  // sol üstte    }}

Kök yığına itilir: [1].

1234567Yığın32üstÇıktı: 1şimdiyapıdayazdırıldı
public void kokBastaYigin(AgacDugumu kok) {    if (kok == null) return;    Stack<AgacDugumu> yigit = new Stack<>();    yigit.push(kok);    while (!yigit.isEmpty()) {        AgacDugumu gecici = yigit.pop();        System.out.print(gecici.veri + " ");        if (gecici.sag != null)            yigit.push(gecici.sag);  // önce sağ        if (gecici.sol != null)            yigit.push(gecici.sol);  // sol üstte    }}

1 çıkarılıp yazdırılır; önce sağ (3), sonra sol (2) itilir → 2 üstte.

1234567Yığın354üstÇıktı: 1 2şimdiyapıdayazdırıldı
public void kokBastaYigin(AgacDugumu kok) {    if (kok == null) return;    Stack<AgacDugumu> yigit = new Stack<>();    yigit.push(kok);    while (!yigit.isEmpty()) {        AgacDugumu gecici = yigit.pop();        System.out.print(gecici.veri + " ");        if (gecici.sag != null)            yigit.push(gecici.sag);  // önce sağ        if (gecici.sol != null)            yigit.push(gecici.sol);  // sol üstte    }}

2 çıkarılır, yazdırılır; 5 ve 4 itilir.

1234567Yığın35üstÇıktı: 1 2 4şimdiyapıdayazdırıldı
public void kokBastaYigin(AgacDugumu kok) {    if (kok == null) return;    Stack<AgacDugumu> yigit = new Stack<>();    yigit.push(kok);    while (!yigit.isEmpty()) {        AgacDugumu gecici = yigit.pop();        System.out.print(gecici.veri + " ");        if (gecici.sag != null)            yigit.push(gecici.sag);  // önce sağ        if (gecici.sol != null)            yigit.push(gecici.sol);  // sol üstte    }}

4 çıkarılır, yazdırılır; çocuğu yok.

1234567Yığın3üstÇıktı: 1 2 4 5şimdiyapıdayazdırıldı
public void kokBastaYigin(AgacDugumu kok) {    if (kok == null) return;    Stack<AgacDugumu> yigit = new Stack<>();    yigit.push(kok);    while (!yigit.isEmpty()) {        AgacDugumu gecici = yigit.pop();        System.out.print(gecici.veri + " ");        if (gecici.sag != null)            yigit.push(gecici.sag);  // önce sağ        if (gecici.sol != null)            yigit.push(gecici.sol);  // sol üstte    }}

5 çıkarılır, yazdırılır.

1234567Yığın76üstÇıktı: 1 2 4 5 3şimdiyapıdayazdırıldı
public void kokBastaYigin(AgacDugumu kok) {    if (kok == null) return;    Stack<AgacDugumu> yigit = new Stack<>();    yigit.push(kok);    while (!yigit.isEmpty()) {        AgacDugumu gecici = yigit.pop();        System.out.print(gecici.veri + " ");        if (gecici.sag != null)            yigit.push(gecici.sag);  // önce sağ        if (gecici.sol != null)            yigit.push(gecici.sol);  // sol üstte    }}

3 çıkarılır, yazdırılır; 7 ve 6 itilir.

1234567Yığın7üstÇıktı: 1 2 4 5 3 6şimdiyapıdayazdırıldı
public void kokBastaYigin(AgacDugumu kok) {    if (kok == null) return;    Stack<AgacDugumu> yigit = new Stack<>();    yigit.push(kok);    while (!yigit.isEmpty()) {        AgacDugumu gecici = yigit.pop();        System.out.print(gecici.veri + " ");        if (gecici.sag != null)            yigit.push(gecici.sag);  // önce sağ        if (gecici.sol != null)            yigit.push(gecici.sol);  // sol üstte    }}

6 çıkarılır, yazdırılır.

1234567YığınboşÇıktı: 1 2 4 5 3 6 7şimdiyapıdayazdırıldı
public void kokBastaYigin(AgacDugumu kok) {    if (kok == null) return;    Stack<AgacDugumu> yigit = new Stack<>();    yigit.push(kok);    while (!yigit.isEmpty()) {        AgacDugumu gecici = yigit.pop();        System.out.print(gecici.veri + " ");        if (gecici.sag != null)            yigit.push(gecici.sag);  // önce sağ        if (gecici.sol != null)            yigit.push(gecici.sol);  // sol üstte    }}

7 yazdırılır; yığın boş, döngü biter. Çıktı: 1 2 4 5 3 6 7

Gezinmeler

Yığın ile Kök Ortada Gezinme

123456Yığın124üstÇıktı: —şimdiyapıdayazdırıldı
public void kokOrtadaYigin(AgacDugumu kok) {    if (kok == null) return;    Stack<AgacDugumu> yigit = new Stack<>();    AgacDugumu gecici = kok;    while (!yigit.isEmpty() || gecici != null) {        if (gecici != null) {            yigit.push(gecici);            gecici = gecici.sol;        } else {            gecici = yigit.pop();            System.out.print(gecici.veri + " ");            gecici = gecici.sag;        }    }}

gecici null olana kadar sola inilir: 1, 2, 4 itilir; gecici = 4.sol = null.

123456Yığın12üstÇıktı: 4şimdiyapıdayazdırıldı
public void kokOrtadaYigin(AgacDugumu kok) {    if (kok == null) return;    Stack<AgacDugumu> yigit = new Stack<>();    AgacDugumu gecici = kok;    while (!yigit.isEmpty() || gecici != null) {        if (gecici != null) {            yigit.push(gecici);            gecici = gecici.sol;        } else {            gecici = yigit.pop();            System.out.print(gecici.veri + " ");            gecici = gecici.sag;        }    }}

4 çıkarılır, yazdırılır; gecici = 4.sag = null.

123456Yığın15üstÇıktı: 4 2şimdiyapıdayazdırıldı
public void kokOrtadaYigin(AgacDugumu kok) {    if (kok == null) return;    Stack<AgacDugumu> yigit = new Stack<>();    AgacDugumu gecici = kok;    while (!yigit.isEmpty() || gecici != null) {        if (gecici != null) {            yigit.push(gecici);            gecici = gecici.sol;        } else {            gecici = yigit.pop();            System.out.print(gecici.veri + " ");            gecici = gecici.sag;        }    }}

2 çıkarılır, yazdırılır; gecici = 5 → 5 itilir, gecici = null.

123456Yığın1üstÇıktı: 4 2 5şimdiyapıdayazdırıldı
public void kokOrtadaYigin(AgacDugumu kok) {    if (kok == null) return;    Stack<AgacDugumu> yigit = new Stack<>();    AgacDugumu gecici = kok;    while (!yigit.isEmpty() || gecici != null) {        if (gecici != null) {            yigit.push(gecici);            gecici = gecici.sol;        } else {            gecici = yigit.pop();            System.out.print(gecici.veri + " ");            gecici = gecici.sag;        }    }}

5 çıkarılır, yazdırılır; gecici = null.

123456Yığın36üstÇıktı: 4 2 5 1şimdiyapıdayazdırıldı
public void kokOrtadaYigin(AgacDugumu kok) {    if (kok == null) return;    Stack<AgacDugumu> yigit = new Stack<>();    AgacDugumu gecici = kok;    while (!yigit.isEmpty() || gecici != null) {        if (gecici != null) {            yigit.push(gecici);            gecici = gecici.sol;        } else {            gecici = yigit.pop();            System.out.print(gecici.veri + " ");            gecici = gecici.sag;        }    }}

1 çıkarılır, yazdırılır; gecici = 3 → 3 ve 6 itilir.

123456Yığın3üstÇıktı: 4 2 5 1 6şimdiyapıdayazdırıldı
public void kokOrtadaYigin(AgacDugumu kok) {    if (kok == null) return;    Stack<AgacDugumu> yigit = new Stack<>();    AgacDugumu gecici = kok;    while (!yigit.isEmpty() || gecici != null) {        if (gecici != null) {            yigit.push(gecici);            gecici = gecici.sol;        } else {            gecici = yigit.pop();            System.out.print(gecici.veri + " ");            gecici = gecici.sag;        }    }}

6 çıkarılır, yazdırılır; gecici = null.

123456YığınboşÇıktı: 4 2 5 1 6 3şimdiyapıdayazdırıldı
public void kokOrtadaYigin(AgacDugumu kok) {    if (kok == null) return;    Stack<AgacDugumu> yigit = new Stack<>();    AgacDugumu gecici = kok;    while (!yigit.isEmpty() || gecici != null) {        if (gecici != null) {            yigit.push(gecici);            gecici = gecici.sol;        } else {            gecici = yigit.pop();            System.out.print(gecici.veri + " ");            gecici = gecici.sag;        }    }}

3 yazdırılır; gecici = null ve yığın boş → biter. Çıktı: 4 2 5 1 6 3

Gezinmeler

Yığın ile Kök Sonda Gezinme: Kod

public void kokSondaYigin(AgacDugumu kok) {
  AgacDugumu simdiki = kok;
  Stack<AgacDugumu> yigit = new Stack<>();
  while (simdiki != null || !yigit.isEmpty()) {
    if (simdiki != null) {
      yigit.push(simdiki);
      simdiki = simdiki.sol;
    } else {
      AgacDugumu gecici = yigit.peek().sag;
      if (gecici == null) {
        gecici = yigit.pop();
        System.out.print(gecici.veri + " ");
        while (!yigit.isEmpty()
           && gecici == yigit.peek().sag) {
          gecici = yigit.pop();
          System.out.print(gecici.veri + " ");
        }
      } else {
        simdiki = gecici;
      }
    }
  }
}
  • Kök, iki alt ağacı da bittikten sonra yazdırılmalı; bu yüzden yığındaki düğüm hemen çıkarılmaz, önce peek ile bakılır.
  • Üstteki düğümün sağ çocuğu varsa önce o alt ağaca gidilir.
  • Sağ çocuk yoksa düğüm yazdırılır. Az önce yazdırılan düğüm, yığındakinin sağ çocuğuysa o ebeveynin de işi bitmiştir → o da çıkarılıp yazdırılır.

Gezinmeler

Yığın ile Kök Sonda Gezinme: İzleme

123456Yığın124üstÇıktı: —şimdiyapıdayazdırıldı
simdiki null olana dek sola inilir: 1, 2, 4 itilir.
123456Yığın12üstÇıktı: 4şimdiyapıdayazdırıldı
peek = 4, 4.sag null → 4 çıkarılıp yazdırılır. 4, 2'nin sağ çocuğu değil; iç döngü durur.
123456Yığın125üstÇıktı: 4şimdiyapıdayazdırıldı
peek = 2, 2.sag = 5 ≠ null → simdiki = 5; 5 itilir, 5.sol null.
123456Yığın1üstÇıktı: 4 5 2şimdiyapıdayazdırıldı
5.sag null → 5 yazdırılır. 5 == 2.sag olduğu için 2 de çıkarılıp yazdırılır.
123456Yığın13üstÇıktı: 4 5 2şimdiyapıdayazdırıldı
peek = 1, 1.sag = 3 → simdiki = 3; 3 itilir, 3.sol null.
123456Yığın136üstÇıktı: 4 5 2şimdiyapıdayazdırıldı
peek = 3, 3.sag = 6 → simdiki = 6; 6 itilir.
123456YığınboşÇıktı: 4 5 2 6 3 1şimdiyapıdayazdırıldı
6 yazdırılır; 6 == 3.sag → 3; 3 == 1.sag → 1. Yığın boş. Çıktı: 4 5 2 6 3 1

Gezinmeler

Kuyruk ile Seviye Sırası Gezinme

43758Kuyruk4önÇıktı: —şimdikuyruktayazdırıldı
public void seviyeSirasi(AgacDugumu kok) {    if (kok == null) return;    Queue<AgacDugumu> kuyruk = new LinkedList<>();    kuyruk.add(kok);    while (!kuyruk.isEmpty()) {        AgacDugumu gecici = kuyruk.poll();        System.out.print(gecici.veri + " ");        if (gecici.sol != null)            kuyruk.add(gecici.sol);        if (gecici.sag != null)            kuyruk.add(gecici.sag);    }}

Kök kuyruğa eklenir: [4].

43758Kuyruk37önÇıktı: 4şimdikuyruktayazdırıldı
public void seviyeSirasi(AgacDugumu kok) {    if (kok == null) return;    Queue<AgacDugumu> kuyruk = new LinkedList<>();    kuyruk.add(kok);    while (!kuyruk.isEmpty()) {        AgacDugumu gecici = kuyruk.poll();        System.out.print(gecici.veri + " ");        if (gecici.sol != null)            kuyruk.add(gecici.sol);        if (gecici.sag != null)            kuyruk.add(gecici.sag);    }}

4 kuyruğun önünden alınır, yazdırılır; çocukları 3 ve 7 arkaya eklenir.

43758Kuyruk758önÇıktı: 4 3şimdikuyruktayazdırıldı
public void seviyeSirasi(AgacDugumu kok) {    if (kok == null) return;    Queue<AgacDugumu> kuyruk = new LinkedList<>();    kuyruk.add(kok);    while (!kuyruk.isEmpty()) {        AgacDugumu gecici = kuyruk.poll();        System.out.print(gecici.veri + " ");        if (gecici.sol != null)            kuyruk.add(gecici.sol);        if (gecici.sag != null)            kuyruk.add(gecici.sag);    }}

3 alınır, yazdırılır; 5 ve 8 arkaya eklenir.

43758Kuyruk58önÇıktı: 4 3 7şimdikuyruktayazdırıldı
public void seviyeSirasi(AgacDugumu kok) {    if (kok == null) return;    Queue<AgacDugumu> kuyruk = new LinkedList<>();    kuyruk.add(kok);    while (!kuyruk.isEmpty()) {        AgacDugumu gecici = kuyruk.poll();        System.out.print(gecici.veri + " ");        if (gecici.sol != null)            kuyruk.add(gecici.sol);        if (gecici.sag != null)            kuyruk.add(gecici.sag);    }}

7 alınır, yazdırılır; çocuğu yok.

43758Kuyruk8önÇıktı: 4 3 7 5şimdikuyruktayazdırıldı
public void seviyeSirasi(AgacDugumu kok) {    if (kok == null) return;    Queue<AgacDugumu> kuyruk = new LinkedList<>();    kuyruk.add(kok);    while (!kuyruk.isEmpty()) {        AgacDugumu gecici = kuyruk.poll();        System.out.print(gecici.veri + " ");        if (gecici.sol != null)            kuyruk.add(gecici.sol);        if (gecici.sag != null)            kuyruk.add(gecici.sag);    }}

5 alınır, yazdırılır.

43758KuyrukboşÇıktı: 4 3 7 5 8şimdikuyruktayazdırıldı
public void seviyeSirasi(AgacDugumu kok) {    if (kok == null) return;    Queue<AgacDugumu> kuyruk = new LinkedList<>();    kuyruk.add(kok);    while (!kuyruk.isEmpty()) {        AgacDugumu gecici = kuyruk.poll();        System.out.print(gecici.veri + " ");        if (gecici.sol != null)            kuyruk.add(gecici.sol);        if (gecici.sag != null)            kuyruk.add(gecici.sag);    }}

8 yazdırılır; kuyruk boş. Çıktı: 4 3 7 5 8 (kök başta olsaydı: 4 3 5 8 7)

Gezinmeler

Uygulama: İfade Ağacı

  • İç düğümler işleçler, yapraklar işlenenlerdir.
  • Aynı ağaç, gezinme türüne göre farklı gösterimler verir.
  • Değer, kök sonda gezinmeyle hesaplanır: önce iki alt ağacın değeri, sonra işleç.
×+−3452
GezinmeÇıktıGösterim
Kök başta× + 3 4 − 5 2önek (prefix)
Kök ortada3 + 4 × 5 − 2 → parantezle: (3 + 4) × (5 − 2)ara ek (infix)
Kök sonda3 4 + 5 2 − × → 7 × 3 = 21sonek (postfix)

Kök ortada çıktısında parantez kaybolur; ifadeyi doğru yazmak için her alt ağaç parantez içine alınmalıdır. Bkz. Bölüm 4 infix → postfix simülatörü.

Gezinmeler

İkili Ağaçta En Büyük Değeri Bulma

43758
1public int enBuyukBul(AgacDugumu kok) {2    if (kok == null) {3        return Integer.MIN_VALUE;4    }5    int sonuc = kok.veri;6    int sol = enBuyukBul(kok.sol);7    int sag = enBuyukBul(kok.sag);8    if (sol > sonuc)9        sonuc = sol;10    if (sag > sonuc)11        sonuc = sag;12    return sonuc;13}

enBuyukBul(4): sonuc = 4; önce sol alt ağaç (3) çağrılır.

43758→ 5
1public int enBuyukBul(AgacDugumu kok) {2    if (kok == null) {3        return Integer.MIN_VALUE;4    }5    int sonuc = kok.veri;6    int sol = enBuyukBul(kok.sol);7    int sag = enBuyukBul(kok.sag);8    if (sol > sonuc)9        sonuc = sol;10    if (sag > sonuc)11        sonuc = sag;12    return sonuc;13}

5 yaprak: iki çocuğu MIN_VALUE döndürür → 5 döner.

43758→ 5→ 8
1public int enBuyukBul(AgacDugumu kok) {2    if (kok == null) {3        return Integer.MIN_VALUE;4    }5    int sonuc = kok.veri;6    int sol = enBuyukBul(kok.sol);7    int sag = enBuyukBul(kok.sag);8    if (sol > sonuc)9        sonuc = sol;10    if (sag > sonuc)11        sonuc = sag;12    return sonuc;13}

8 yaprak → 8 döner.

43758→ 5→ 8→ 8
1public int enBuyukBul(AgacDugumu kok) {2    if (kok == null) {3        return Integer.MIN_VALUE;4    }5    int sonuc = kok.veri;6    int sol = enBuyukBul(kok.sol);7    int sag = enBuyukBul(kok.sag);8    if (sol > sonuc)9        sonuc = sol;10    if (sag > sonuc)11        sonuc = sag;12    return sonuc;13}

Düğüm 3: sonuc = 3; sol = 5 > 3 → 5; sag = 8 > 5 → 8 döner.

43758→ 5→ 8→ 8→ 7
1public int enBuyukBul(AgacDugumu kok) {2    if (kok == null) {3        return Integer.MIN_VALUE;4    }5    int sonuc = kok.veri;6    int sol = enBuyukBul(kok.sol);7    int sag = enBuyukBul(kok.sag);8    if (sol > sonuc)9        sonuc = sol;10    if (sag > sonuc)11        sonuc = sag;12    return sonuc;13}

7 yaprak → 7 döner.

43758→ 5→ 8→ 8→ 7→ 8
1public int enBuyukBul(AgacDugumu kok) {2    if (kok == null) {3        return Integer.MIN_VALUE;4    }5    int sonuc = kok.veri;6    int sol = enBuyukBul(kok.sol);7    int sag = enBuyukBul(kok.sag);8    if (sol > sonuc)9        sonuc = sol;10    if (sag > sonuc)11        sonuc = sag;12    return sonuc;13}

Kök: sonuc = 4; sol = 8 → 8; sag = 7 < 8. Sonuç: 8

Gezinmeler

Özyinelemeli Ağaç Fonksiyonları

int boyut(AgacDugumu k) {            // düğüm sayısı
    if (k == null) return 0;
    return 1 + boyut(k.sol) + boyut(k.sag);
}

int yukseklik(AgacDugumu k) {        // kenar sayısı
    if (k == null) return -1;        // boş ağaç: -1
    return 1 + Math.max(yukseklik(k.sol),
                        yukseklik(k.sag));
}

int yaprakSayisi(AgacDugumu k) {
    if (k == null) return 0;
    if (k.sol == null && k.sag == null) return 1;
    return yaprakSayisi(k.sol) + yaprakSayisi(k.sag);
}
Ortak kalıpBoş ağaç için taban durum; aksi halde iki alt ağacın sonucunu birleştir (kök sonda mantığı).
9 → (2 → 4), 3 ağacındaboyut = 4yukseklik = 2yaprakSayisi = 2 (4 ve 3)
MaliyetHer düğüm bir kez işlenir: O(n) zaman, O(h) yığın alanı.

Gezinmeler

Gezinmelerin Maliyeti

YöntemZamanEk bellekNeden?
Özyinelemeli pre/in/postO(n)O(h)Çağrı yığınında en fazla h + 1 çerçeve
Yığın ile pre/in/postO(n)O(h)Açık yığın, özyinelemenin yerini tutar
Kuyruk ile seviye sırasıO(n)O(w)w: en geniş düzeydeki düğüm sayısı
h ne kadar?Dengeli ağaçta h ≈ log2 n; çarpık ağaçta h = n − 1. Çok derin ağaçlarda özyineleme StackOverflowError verebilir → yığınlı sürüm tercih edilir.
w ne kadar?Mükemmel ağaçta son düzeyde ≈ n/2 düğüm vardır; seviye sırası geniş ağaçlarda daha çok bellek harcar.

Çok Yollu Ağaçlar

B-Ağacı (B-Tree)

  • Bir düğümde birden çok anahtar ve çok sayıda çocuk bulunan, dengeli bir çok yollu arama ağacıdır.
  • Derecesi m olan B-ağacında bir düğüm en fazla m çocuk, m − 1 anahtar tutar; kök dışındaki düğümlerde en az ⌈m/2⌉ çocuk bulunur.
  • Düğüm içindeki anahtarlar sıralıdır; tüm yapraklar aynı derinliktedir.
  • Yükseklik O(log n) kalır; ekleme/silmede düğümler bölünür veya birleştirilir.
2040510253035506030 aranıyor: 20 < 30 < 40 → orta çocuk
Neden? Bir düğüm bir disk bloğuna denk getirilir. Geniş ve alçak ağaç = az disk erişimi. Veritabanı ve dosya sistemi indekslerinin temelidir.

B-ağacı, (a,b) ağacının özel bir hâlidir. Adım adım ekleme ve bölünme için: B-Ağacı simülatörü.

Çok Yollu Ağaçlar

B+ Ağacı (B+ Tree)

2040510202530405060yapraklar bağlı liste: aralık sorgusu soldan sağa okunur
Veri yapraklardaTüm anahtarlar (ve kayıtlar) yapraklarda bulunur; iç düğümler yalnızca yönlendirme anahtarı tutar.
Bağlı yapraklarYapraklar birbirine bağlıdır; "20 ile 50 arası" gibi aralık sorguları hızlıdır.
Daha geniş iç düğümlerİç düğümler kayıt taşımadığından bir bloğa daha çok anahtar sığar → ağaç daha alçak.

Çoğu ilişkisel veritabanı indeksi B+ ağacıdır. Deneyin: B+ Ağacı simülatörü.

Özet

Özet

KonuHatırlanacaklar
Terimlerkök, ebeveyn/çocuk, yaprak, iç düğüm; n düğüm → n − 1 kenar
Ölçülerderece = çocuk sayısı; derinlik = kökten kenar sayısı; yükseklik = en uzun aşağı yol
İkili ağaçdolu: 0/2 çocuk · tam: son düzey soldan dolar · mükemmel: tüm düzeyler dolu
Gösterimdizi: indeks bağıntıları · bağlı: sol/sağ başvuruları
Gezinmekök başta K-S-S · kök ortada S-K-S · kök sonda S-S-K · seviye sırası kuyrukla
Maliyettüm gezinmeler O(n); ek bellek O(h) (yığın) veya O(w) (kuyruk)
B / B+ ağacıçok yollu, dengeli, yapraklar aynı derinlikte; disk tabanlı indeksler

Özet

Etkileşimli Simülatörler

Genel AğaçÇocuk sayısı sınırsız ağaçta düğüm ekleme/silme ve gezinmeler.
İkili (Arama) Ağaçİkili ağaç üzerinde ekleme ve kök başta / ortada / sonda gezinmeleri izleme.
B-AğacıAnahtar ekledikçe düğümlerin bölünmesini ve ağacın dengeli büyümesini izleyin.
B+ AğacıVerinin yapraklarda tutulduğu, yaprakları bağlı çok yollu ağaç.

Özet

Örnek Problemler

  1. Sağdaki ağacın kök başta, kök ortada, kök sonda ve seviye sırası çıktılarını yazın.
  2. Ağacın yüksekliği nedir? Yapraklar hangileri? E'nin derinliği kaçtır?
  3. Bu ağaç dolu mu, tam mı, mükemmel mi?
  4. 1 tabanlı dizi gösteriminde F ve G hangi indislerde durur? Dizi en az kaç hücre olmalı?
  5. Yüksekliği 4 olan bir ikili ağaçta en fazla kaç düğüm olabilir?
  6. Kök başta: A B D E C F, kök ortada: D B E A C F. Ağacı çizin.
ABCDEFG
Cevapları göster
  1. Kök başta: A B D E G C F · kök ortada: D B G E A C F · kök sonda: D G E B F C A · seviye: A B C D E F G
  2. Yükseklik 3 (A→B→E→G); yapraklar D, G, F; E'nin derinliği 2.
  3. Hiçbiri: E ve C'nin tek çocuğu var (dolu değil); 6. konum boşken 7 dolu (tam değil).
  4. F: C'nin sağ çocuğu → 2·3 + 1 = 7; G: E'nin sol çocuğu → 2·5 = 10. En az 10 hücre (1..10).
  5. 25 − 1 = 31.
  6. A kök; sol alt ağaç {D, B, E}: B kök, D sol, E sağ; sağ alt ağaç {C, F}: C kök, F sağ çocuk.

Özet

Kaynaklar

  • Goodrich, Tamassia ve Goldwasser, Data Structures and Algorithms in Java, 6. baskı, 2014.
  • Cormen, Leiserson, Rivest ve Stein, Introduction to Algorithms, 4. baskı, 2022.
  • Sedgewick ve Wayne, Algorithms, 4. baskı, 2011.

Son

Bölüm 7: Ağaçlar
Sonraki bölüm: Öncelikli Kuyruklar ve Heap
1 / 1 Sercan KÜLCÜ, Tüm hakları saklıdır.

← → veya boşluk ile gezinin · F: tam ekran · Home/End: ilk/son slayt