Bir listeye veri eklerken onu sıralı tutmak isterseniz genelde her ekleme sonrası listeyi baştan sıralarsınız. Peki ya veri, eklendiği anda kendiliğinden doğru yere yerleşseydi? İşte tam bu ihtiyacı karşılayan yapı, bilgisayar bilimlerinin en temel taşlarından biri olan İkili Arama Ağacı’dır (Binary Search Tree – BST).
Bu Proje Ne Yapıyor?
Bu projede, herhangi bir hazır kütüphane kullanmadan, sıfırdan bir İkili Arama Ağacı kuruyoruz. Amaç, düz bir liste yerine düğümlerden (node) oluşan hiyerarşik bir yapı kurarak hem veri ekleme hem de arama işlemlerini ortalama $O(\log n)$ zaman karmaşıklığında gerçekleştirebilmek.
Program iki ana sınıftan oluşuyor: tek bir veriyi ve onun sol/sağ çocuklarına giden bağlantıları (pointer/referans) tutan Node, bir de bu düğümleri birbirine bağlayan ve üzerinde işlem yapılan BinarySearchTree. Örnek çalıştırmada [50, 30, 70, 20, 40, 60, 80] gibi karışık sıralı bir veri kümesi ağaca ekleniyor, ardından ağaç sıra içi (in-order) dolaşımla gezilerek verinin otomatik olarak sıralanmış hâlde çıktığı gösteriliyor. Son olarak birkaç hedef değer için arama yapılarak ağacın var olan ve olmayan elemanları nasıl ayırt ettiği test ediliyor.
Neden düz bir Python listesi yerine böyle bir yapı kuruyoruz? Çünkü sıralı bir listede yeni bir eleman eklemek istediğinizde doğru konumu bulmak ve diğer elemanları kaydırmak $O(n)$ zaman alır. BST’de ise ağacın yüksekliği kadar (ortalama $\log n$ adım) karşılaştırma yaparak hem ekleme hem arama işlemini tamamlarsınız. Bu yüzden BST’ler; veritabanı indeksleri, dosya sistemleri ve otomatik tamamlama gibi hızlı arama gerektiren pek çok gerçek dünya sisteminin temelinde yer alır.
Kodun Anatomisi
İkili Arama Ağacı’nın kalbinde tek bir kural var: bir düğümün solundaki her değer o düğümden küçük, sağındaki her değer ise ona eşit veya büyük olmalı. Bu basit kural, tüm yapının hem sıralı kalmasını hem de hızlı aranabilmesini sağlıyor.
insert metodu, ağaç boşsa yeni değeri doğrudan köke (root) yerleştiriyor; değilse _insert_recursive adlı yardımcı metoda devrediyor. Bu metot, özyineleme (recursion) kullanarak değeri mevcut düğümle karşılaştırıyor ve boş bir yaprak (leaf) pozisyonu bulana kadar sola ya da sağa iniyor.
class Node:
"""Ağaçtaki tek bir düğümü temsil eder."""
def __init__(self, value: int) -> None:
self.value: int = value
self.left: Node | None = None
self.right: Node | None = None
class BinarySearchTree:
def __init__(self) -> None:
self.root: Node | None = None
def insert(self, value: int) -> None:
if self.root is None:
self.root = Node(value)
else:
self._insert_recursive(self.root, value)
def _insert_recursive(self, current_node: Node, value: int) -> None:
if value < current_node.value:
if current_node.left is None:
current_node.left = Node(value)
else:
self._insert_recursive(current_node.left, value)
else:
if current_node.right is None:
current_node.right = Node(value)
else:
self._insert_recursive(current_node.right, value)
search metodu da aynı mantıkla çalışıyor ama bu sefer amaç eklemek değil, bulmak. BST’nin sıralı yapısı sayesinde her adımda ağacın yarısını eleyebiliyoruz; bu yüzden ortalama durumda arama süresi $O(\log n)$’e iniyor, yani milyonlarca elemanlı bir ağaçta bile birkaç karşılaştırmayla sonuca ulaşabiliyoruz.
def search(self, target: int) -> bool:
return self._search_recursive(self.root, target)
def _search_recursive(self, current_node: Node | None, target: int) -> bool:
if current_node is None:
return False
if current_node.value == target:
return True
if target < current_node.value:
return self._search_recursive(current_node.left, target)
return self._search_recursive(current_node.right, target)
Dikkat ederseniz _search_recursive, hedef değer mevcut düğümden küçükse sağ tarafa hiç bakmadan doğrudan sol alt ağaca yöneliyor. İşte hız kazandıran asıl detay bu: her adımda aramanız gereken alanı yarıya indiriyorsunuz, tıpkı bir sözlükte sayfaları ortadan ikiye katlayarak aradığınız kelimeye yaklaşmak gibi.
Asıl sihir ise get_inorder_list metodunda gizli: önce sol alt ağacı, sonra kök düğümü, en son sağ alt ağacı ziyaret eden bu “sıra içi dolaşım” (in-order traversal), geçerli bir BST üzerinde çalıştırıldığında verileri her zaman küçükten büyüğe sıralı biçimde döndürüyor. Yani ağaç, kurulduğu andan itibaren kendi sıralama mantığını içinde taşıyor.
Ortam Bilgisi
Yazar: Ahmet Aksoy · Tarih: 23.05.2026 · Python 3.12 · Ubuntu 24.04
Nasıl Çalıştırılır?
Projeyi çalıştırmak için ek bir bağımlılık kurmanıza gerek yok; sadece standart kütüphane kullanılıyor. Tek gereksinim, kodun kullandığı Node | None birleşim (union) tip gösterimi ve typing.Self sebebiyle Python 3.12 veya üzeri bir sürüm.
python main.py
Çalıştırdığınızda önce karışık sırayla eklenen sayıların ağaca yerleştirildiğini, ardından sıra içi dolaşımın bu sayıları sıralı biçimde döndürdüğünü, son olarak da hedef değerlerin ağaçta bulunup bulunmadığını gösteren bir çıktı alırsınız:
In-Order Traversal Output (Sorted): [20, 30, 40, 50, 60, 70, 80]
Searching for target element [40]: FOUND
Searching for target element [99]: NOT FOUND
Ne Öğrendik?
- Nesne yönelimli programlama (OOP) kullanarak birbirine bağlı
Nodenesneleriyle hiyerarşik bir veri yapısı nasıl kurulur. - Özyineleme (recursion), bir ağacı dolaşırken tekrar tekrar aynı mantığı daha küçük alt problemlere nasıl uygular.
- Bir İkili Arama Ağacı’nın “sol küçük, sağ büyük” kuralı sayesinde arama işlemlerinin neden lineer değil logaritmik zamanda çalıştığı.
- Sıra içi dolaşımın (in-order traversal), doğru kurulmuş bir BST’den her zaman sıralı bir liste çıkardığı — yani ağaç, aslında kendi kendini sıralayan bir yapı.
- Pointer/referans tabanlı yapıların, Python’da
Noneile karşılaştırmalar ve iç içe nesne bağlantıları üzerinden nasıl kurulduğu — bu mantık, bağlı listeler (linked list) ve graf yapıları gibi ileri veri yapılarına da doğrudan taşınabiliyor.
Kaynaklar ve Sonraki Adımlar
Bu temel yapıyı geliştirmek isterseniz sırasıyla şunları deneyebilirsiniz: bir delete metodu ekleyerek düğüm silme mantığını kurmak, ağacın dengesiz büyümesini önlemek için AVL veya Kırmızı-Siyah Ağaç (Red-Black Tree) gibi kendi kendini dengeleyen varyantlara göz atmak, ya da graphviz gibi bir kütüphaneyle ağacı görsel olarak çizdirmek. Her biri, veri yapıları dünyasında bir sonraki adımınız için harika birer alıştırma.
Ahmet Aksoy
Not: Bu yazıda incelediğimiz kodu ve benzer projelerin kaynak kodlarını github.com/ahmetax/practical-python-examples adresinde bulabilirsiniz.