🌳 5.1: İkili Arama Ağacı (BST) Nedir?

Binary Search Tree - Hızlı Arama için Ağaç Yapısı

🤔 Neden Yeni Bir Veri Yapısına İhtiyacımız Var?

Şimdiye kadar öğrendiğimiz veri yapılarını düşünelim ve bir problemi ele alalım:

📱 Senaryo: Telefon Rehberi Uygulaması

Bir telefon rehberi uygulaması yazıyorsunuz. Kullanıcılar:

  • Arama: İsme göre numara bulma
  • Ekleme: Yeni kişi ekleme
  • Silme: Kişi silme

Bu üç işlemi de hızlı yapan bir yapıya ihtiyacımız var!

Mevcut Seçeneklerimiz Neden Yetersiz?

📋 Sırasız Dizi

Ekleme hızlı (sona ekle) ama arama çok yavaş - tüm diziyi taramak gerekir.

Arama:O(n) 😟
Ekleme:O(1) 😊
Silme:O(n) 😟

📋 Sıralı Dizi

Binary search ile arama hızlı, ama ekleme/silme için kaydırma gerekir.

Arama:O(log n) 😊
Ekleme:O(n) 😟
Silme:O(n) 😟

🔗 Linked List

Ekleme/silme kolay, ama sıralı tutulsa bile arama için baştan taramak gerekir.

Arama:O(n) 😟
Ekleme:O(1)* 😊
Silme:O(n) 😟

*Pozisyon biliniyorsa

💡 Çözüm: İkili Arama Ağacı (BST)

BST, hem arama hem ekleme hem silme işlemlerini O(log n)'de yapabilir!

İşlem BST (Dengeli)
AramaO(log n) 😊
EklemeO(log n) 😊
SilmeO(log n) 😊

🎯 İkili Arama Ağacı (BST) Özelliği

BST, ikili ağaçlara (binary tree) özel bir kural ekler. Bu kural sayesinde arama çok hızlı olur:

🔑 BST Kuralı (Her Zaman Geçerli!)

Ağaçtaki her node için şu kural geçerlidir:

⬅️
Sol alt ağaçtaki TÜM değerler
< Node
➡️
Sağ alt ağaçtaki TÜM değerler
> Node

Bu basit kural, her karşılaştırmada arama alanını yarıya indirmemizi sağlar!

⚠️ Dikkat: "TÜM değerler" Önemli!

Sadece direkt çocuklar değil, tüm alt ağaç için geçerli:

        50
       /  \
     30    70
    / \   /  \
   20 40 60  80
            

50'nin sol alt ağacındaki TÜM değerler (20, 30, 40) < 50
50'nin sağ alt ağacındaki TÜM değerler (60, 70, 80) > 50

🎮 İnteraktif BST Görselleştirme

Değer girin ve "Ekle" butonuna tıklayın

🧱 Node (Düğüm) Yapısı

BST node'u, linked list node'una benzer ama iki referans içerir:

LEFT
DATA
50
RIGHT
Python Kodu
# BST için Node sınıfı
class Node:
    def __init__(self, data):
        self.data = data      # Saklanan değer
        self.left = None      # Sol çocuğa referans (küçükler)
        self.right = None     # Sağ çocuğa referans (büyükler)

# Örnek: Basit bir ağaç oluşturalım
#        50
#       /  \
#      30   70
#     / \   / \
#    20 40 60 80

root = Node(50)
root.left = Node(30)
root.right = Node(70)

root.left.left = Node(20)
root.left.right = Node(40)
root.right.left = Node(60)
root.right.right = Node(80)

# Yapıyı kontrol edelim
print("🌳 Ağaç Yapısı:")
print(f"Kök: {root.data}")
print(f"  Sol çocuk: {root.left.data}")
print(f"    Sol-sol: {root.left.left.data}")
print(f"    Sol-sağ: {root.left.right.data}")
print(f"  Sağ çocuk: {root.right.data}")
print(f"    Sağ-sol: {root.right.left.data}")
print(f"    Sağ-sağ: {root.right.right.data}")

# BST kuralını kontrol edelim
print("\n✅ BST Kuralı Kontrolü:")
print(f"  30 < 50 < 70? {root.left.data} < {root.data} < {root.right.data}")
print(f"  20 < 30 < 40? {root.left.left.data} < {root.left.data} < {root.left.right.data}")
print(f"  60 < 70 < 80? {root.right.left.data} < {root.right.data} < {root.right.right.data}")
Çıktı bekleniyor...

📊 Neden BST? Performans Karşılaştırması

📋 Sıralı Dizi

Arama:O(n) (sıralıysa O(log n))
Ekleme:O(n) (kaydırma gerekir)
Silme:O(n) (kaydırma gerekir)

🔗 Linked List

Arama:O(n)
Ekleme (başa):O(1)
Silme:O(n) (arama + O(1))

🌳 BST (Dengeli)

Arama:O(log n)
Ekleme:O(log n)
Silme:O(log n)

⚠️ Önemli Not: Dengesiz BST

Eğer elemanlar sıralı eklenirse (1, 2, 3, 4, 5...), BST bir "linked list"e dönüşür ve performans O(n) olur!

Bu problemi çözmek için AVL Tree veya Red-Black Tree gibi dengeli ağaçlar kullanılır.

🔍 BST'de Arama Nasıl Çalışır?

BST'nin gücü, ikili arama (binary search) mantığından gelir. Her karşılaştırmada arama alanı yarıya iner!

💭 Düşünce Süreci

Her node'da kendimize şunu sorarız:

  1. Eşit mi? → Buldum! 🎉
  2. Aradığım değer küçük mü? → Sol alt ağaca git (büyükler zaten sağda, onlara bakmama gerek yok)
  3. Aradığım değer büyük mü? → Sağ alt ağaca git (küçükler zaten solda)

📝 Adım Adım Örnek: 40'ı Arayalım

                    50  ← Başla
           /  \
         30    70
        /  \   / \
       20  40 60  80
            
Adım 1 Kökten başla: 50 → 40 < 50, sola git!
Adım 2 Şimdi: 30 → 40 > 30, sağa git!
Adım 3 Şimdi: 40 → 40 == 40, BULUNDU! ✅

7 elemanlı ağaçta sadece 3 karşılaştırma ile değeri bulduk!

🎮 İnteraktif Arama Simülasyonu

Bir değer girin ve BST'de nasıl arandığını adım adım izleyin!

📍 Mevcut Konum
-
🛤️ İzlenen Yol
-
💬 Açıklama
Bir değer girin ve "Ara" butonuna tıklayın.
Adım: 0 Karşılaştırma: 0
Python Kodu
class Node:
    def __init__(self, data):
        self.data = data
        self.left = None
        self.right = None

def search(root, target):
    """BST'de arama - O(log n)"""
    steps = 0
    current = root

    while current is not None:
        steps += 1
        print(f"Adım {steps}: {current.data} ile karşılaştır", end=" → ")

        if target == current.data:
            print(f"BULUNDU! ✅")
            return current, steps
        elif target < current.data:
            print(f"{target} < {current.data}, SOLA git")
            current = current.left
        else:
            print(f"{target} > {current.data}, SAĞA git")
            current = current.right

    print("Bulunamadı ❌")
    return None, steps

# Ağacı oluştur
root = Node(50)
root.left = Node(30)
root.right = Node(70)
root.left.left = Node(20)
root.left.right = Node(40)
root.right.left = Node(60)
root.right.right = Node(80)

print("🌳 Ağaç: 50 → (30, 70) → (20, 40, 60, 80)\n")

# Farklı değerleri ara
for target in [40, 80, 25, 50]:
    print(f"\n🔍 {target} aranıyor:")
    result, steps = search(root, target)
    print(f"   Toplam adım: {steps}")
Çıktı bekleniyor...

🌍 Gerçek Hayat Kullanım Alanları

💾 Veritabanı ve Dosya Sistemleri

🖥️ Yazılım Uygulamaları

🎮 Oyun ve Grafik

💡 Neden BST?

Dizide arama: 1 milyon elemanda → 1.000.000 karşılaştırma (O(n))

BST'de arama: 1 milyon elemanda → sadece ~20 karşılaştırma (O(log n))

Bu fark, gerçek dünya uygulamalarında hayati önem taşır!