Diziler ve Bağlı Listeler: Python ile Temel Veri Yapıları Örnekleri
Algoritma ve Veri Yapıları
Diziler ve Bağlı Listeler: Python ile Temel Veri Yapıları Örnekleri

Giriş
Veri yapıları, yazılımda performans ve kaynak kullanımı açısından temel rol oynar. Bu yazıda Python'da sık kullanılan iki yapı olan diziler (Python listeleri) ve bağlı listeleri tanımlıyor; her birinin güçlü ve zayıf yönlerini, basit Python örnekleriyle gösteriyoruz. Amaç, pratik bir bakışla hangi senaryoda hangi yapının tercih edilebileceğini açıkça ortaya koymaktır.
Python'da Diziler (Listeler) — Temel Özellikler
Python'da en sık kullanılan dizi benzeri yapı list tipidir. Listeler sıralı, değiştirilebilir ve indekslenebilir koleksiyonlardır. Eleman tipi heterojendir; farklı türde veri aynı listede tutulabilir. Bu temel özellikler ve kullanım örnekleri için kaynaklara bakabilirsiniz: Kerteriz Blog, LearnPython.org.
Listelerle sık yapılan işlemler — kısa örnek
Aşağıdaki örnek, listelerle temel işlemleri gösterir:
# Liste oluşturma ve temel işlemler
fruits = ['elma', 'armut', 'muz']
print(fruits[0]) # 'elma'
fruits.append('çilek') # sona ekleme
fruits.insert(1, 'kiraz') # belirtilen konuma ekleme
fruits.remove('armut') # değere göre silme
last = fruits.pop() # son elemanı çıkarır ve döndürür
for i, v in enumerate(fruits):
print(i, v) # indeks ve değer ile iterasyon
Listeler, dilin yerleşik özellikleri ve optimize edilmiş C uygulaması sayesinde çoğu görev için hızlı ve pratiktir.
Bağlı Listeler (Linked Lists) — Nedir ve Python'da Nasıl Uygulanır?
Bağlı listeler, her bir düğümün (node) veri ve bir sonraki düğümün adresini (referansını) tuttuğu dinamik yapılar olarak tanımlanır. Bu yapı, düğümlerin rastgele bellek lokasyonlarında depolanmasına ve kolayca ekleme/çıkarma yapılmasına olanak tanır. Bağlı listenin tanımı ve avantajları hakkında daha fazla bilgi için bakılabilecek kaynak: Emre Can Yılmaz.
Basit bir tek yönlü bağlı liste (singly linked list) implementasyonu
Aşağıdaki örnek eğitim amaçlıdır ve temel işlemleri gösterir:
class Node:
def __init__(self, data):
self.data = data
self.next = None
class LinkedList:
def __init__(self):
self.head = None
def prepend(self, data):
node = Node(data)
node.next = self.head
self.head = node
def append(self, data):
node = Node(data)
if not self.head:
self.head = node
return
cur = self.head
while cur.next:
cur = cur.next
cur.next = node
def find(self, key):
cur = self.head
while cur:
if cur.data == key:
return cur
cur = cur.next
return None
def delete(self, key):
cur = self.head
prev = None
while cur:
if cur.data == key:
if prev:
prev.next = cur.next
else:
self.head = cur.next
return True
prev = cur
cur = cur.next
return False
def to_list(self):
out = []
cur = self.head
while cur:
out.append(cur.data)
cur = cur.next
return out
Kullanım örneği
ll = LinkedList()
ll.append(1)
ll.append(2)
ll.prepend(0)
print(ll.to_list()) # [0, 1, 2]
found = ll.find(1)
if found:
print(found.data) # 1
ll.delete(2)
print(ll.to_list()) # [0, 1]
Bu implementasyon, bağlı listenin temel mantığını gösterir. Gerçek uygulamalarda ek hata kontrolleri, iteratör desteği veya kuyruk için tail (son) göstergesi eklemek pratik olabilir.
Zaman Karmaşıklığı: Karşılaştırma
Aşağıdaki tablo, yaygın operasyonlar için algoritmik (Big‑O) karşılaştırma sunar. Gerçek performans, Python uygulamasına (ör. CPython) ve veri boyutuna göre değişebilir.
| Operasyon | Python list (dinamik dizi) | Tek yönlü bağlı liste |
|---|---|---|
| Index ile erişim | O(1) | O(n) |
| Değere göre arama | O(n) | O(n) |
| Başa ekleme/silme | O(n) (öğe kaydırma gerekebilir) | O(1) |
| Sona ekleme | Amortize O(1) | O(n) (tail yoksa), tail ile O(1) |
| Ortadan ekleme/silme | O(n) | O(n) (önce konuma ulaşmak gerekir) |
| Ek bellek | Eleman başına doğrudan depolama; bazı fazladan kapasite ayrılabilir | Her düğüm için ek bir gösterge (next) ve obje üst bilgisi |
Listelerin ardışık hafıza kullanımı ve CPython gibi uygulamalarda kapasite artırımı stratejisi sayesinde append işlemi genelde hızlıdır. Bağlı listeler ise başa/orta ekleme‑çıkarma ihtiyaçlarında algoritmik avantaj sağlar. Bu temel farklar, Python listeler ve bağlı listeler kaynaklarında da ele alınmaktadır.
Hangi Durumda Hangi Veri Yapısını Seçmelisiniz?
- Rastgele erişim (indeksle sık erişim) gerekiyorsa: list tercih edin.
- Çok sık başa ekleme/çıkarma yapacaksanız: bağlı liste veya collections.deque daha uygundur.
- Kuyruk (FIFO) işlemleri için collections.deque kullanmak genellikle listeden daha etkilidir.
- Hafıza ayırma ve temsil biçimi önemliyse, bağlı listenin düğüm başına ekstra maliyeti olduğunu unutmayın.
- Python'da çoğu genel amaçlı uygulama için yerleşik list yapısı ve standart kütüphaneler yeterli ve pratiktir.
Pratik İpuçları ve Test Etme
- Performans gereksinimi varsa timeit veya cProfile ile gerçek ölçümler yapın; teorik karmaşıklık tüm etkileri yakalamayabilir.
- Kuyruk için collections.deque, homojen sayısal veriler için array modülü ya da NumPy gibi kütüphaneler daha iyi alternatifler sunar.
- Bağlı liste implementasyonları eğitim amaçlıdır; üretim kodunda hata yönetimi ve test eklemeyi ihmal etmeyin.
Özet ve İleri Okuma
Python listeleri (diziler) ve bağlı listeler farklı kullanım senaryolarına hizmet eder. Liste yapısı hızlı rastgele erişim ve yerleşik optimizasyonlar sunarken, bağlı liste esnek ekleme/çıkarma operasyonlarını kolaylaştırır. Hangi yapıyı seçeceğiniz, uygulamanızın erişim örüntülerine ve performans gereksinimlerine bağlıdır.
Daha fazla kaynak ve örnekler için bakınız: Python Listeler — Kerteriz Blog, LearnPython.org, Bağlı Listeler — Emre Can Yılmaz.
Not: Makaledeki kod örnekleri temel öğrenme amaçlıdır. Üretim ortamında performans, hata kontrolü ve bellek gereksinimlerini gözlemleyerek eklemeler yapmanız önerilir.