🐍 4.5: Python ile Linked List

Pratik Kullanım ve Performans Karşılaştırması

⚠️ Python'da Linked List Yok mu?

🤔 Önemli Soru

Python'da yerleşik bir LinkedList sınıfı yok. Neden?

  • Python list zaten dinamik dizi implementasyonu
  • collections.deque çoğu linked list işini yapıyor
  • Pratik kullanımda list ve deque yeterli

🔄 collections.deque - En Yakın Alternatif

deque (double-ended queue), içeride doubly linked list kullanır ve O(1) başa/sona ekleme sağlar.

📚 deque Metodları

append(x) O(1) Sona ekle
appendleft(x) O(1) Başa ekle
pop() O(1) Sondan sil
popleft() O(1) Baştan sil
rotate(n) O(k) Döndür (circular gibi!)
Python Kodu
from collections import deque

print("🔄 collections.deque Kullanımı\n")

# Oluşturma
d = deque(['A', 'B', 'C'])
print(f"Başlangıç: {list(d)}")

# Başa ve sona ekleme - O(1)
d.appendleft('X')  # Başa
d.append('Y')      # Sona
print(f"X başa, Y sona: {list(d)}")

# Baştan ve sondan silme - O(1)
d.popleft()  # Baştan
d.pop()      # Sondan
print(f"Baş ve son silindi: {list(d)}")

# Rotate - Circular gibi döndürme!
d = deque([1, 2, 3, 4, 5])
print(f"\nRotate öncesi: {list(d)}")

d.rotate(2)  # Sağa 2 döndür
print(f"rotate(2): {list(d)}")

d.rotate(-3)  # Sola 3 döndür
print(f"rotate(-3): {list(d)}")

# Maxlen - Sabit boyutlu (LRU Cache gibi!)
print(f"\n📦 Sabit boyutlu deque (maxlen=3):")
limited = deque(maxlen=3)
for i in range(5):
    limited.append(i)
    print(f"  append({i}): {list(limited)}")
Çıktı bekleniyor...

🧪 Performans Karşılaştırması

list vs deque: Baştan ekleme/silme yarışı!

Python Kodu
import time
from collections import deque

N = 50000
print(f"🧪 Performans Testi: {N} işlem\n")
print("=" * 50)

# 1. LIST - Başa ekleme
liste = []
start = time.time()
for i in range(N):
    liste.insert(0, i)  # O(n) - her seferinde kaydırma!
list_insert_time = time.time() - start
print(f"📋 list.insert(0, x)  : {list_insert_time:.4f} sn")

# 2. DEQUE - Başa ekleme
kuyruk = deque()
start = time.time()
for i in range(N):
    kuyruk.appendleft(i)  # O(1) - sabit zaman!
deque_append_time = time.time() - start
print(f"🔄 deque.appendleft() : {deque_append_time:.4f} sn")

print(f"\n💡 Deque {list_insert_time/deque_append_time:.0f}x daha hızlı!")

print("\n" + "=" * 50)

# 3. LIST - Baştan silme
liste = list(range(N))
start = time.time()
while liste:
    liste.pop(0)  # O(n)
list_pop_time = time.time() - start
print(f"📋 list.pop(0)        : {list_pop_time:.4f} sn")

# 4. DEQUE - Baştan silme
kuyruk = deque(range(N))
start = time.time()
while kuyruk:
    kuyruk.popleft()  # O(1)
deque_pop_time = time.time() - start
print(f"🔄 deque.popleft()    : {deque_pop_time:.4f} sn")

print(f"\n💡 Deque {list_pop_time/deque_pop_time:.0f}x daha hızlı!")

print("\n" + "=" * 50)
print("\n📊 SONUÇ:")
print("  - Başa ekleme/silme → deque kullan!")
print("  - Random access (index) → list kullan!")
print("  - Sona ekleme/silme → ikisi de O(1)")
Çıktı bekleniyor...

🛠️ Kendi LinkedList Wrapper'ımız

Deque'i sarmalayarak LinkedList benzeri API oluşturalım:

Python Kodu
from collections import deque

class LinkedList:
    """deque tabanlı LinkedList wrapper"""
    
    def __init__(self, iterable=None):
        self._data = deque(iterable) if iterable else deque()
    
    def prepend(self, value):
        """Başa ekle - O(1)"""
        self._data.appendleft(value)
    
    def append(self, value):
        """Sona ekle - O(1)"""
        self._data.append(value)
    
    def pop_first(self):
        """Baştan sil - O(1)"""
        if not self._data:
            raise IndexError("Liste boş!")
        return self._data.popleft()
    
    def pop_last(self):
        """Sondan sil - O(1)"""
        if not self._data:
            raise IndexError("Liste boş!")
        return self._data.pop()
    
    @property
    def head(self):
        """İlk eleman"""
        return self._data[0] if self._data else None
    
    @property
    def tail(self):
        """Son eleman"""
        return self._data[-1] if self._data else None
    
    def __len__(self):
        return len(self._data)
    
    def __iter__(self):
        return iter(self._data)
    
    def __repr__(self):
        return f"LinkedList({list(self._data)})"

# Test
print("🔗 LinkedList Wrapper Demo\n")

ll = LinkedList([1, 2, 3])
print(f"Başlangıç: {ll}")

ll.prepend(0)
ll.append(4)
print(f"0 başa, 4 sona: {ll}")

print(f"Head: {ll.head}, Tail: {ll.tail}")

print(f"pop_first(): {ll.pop_first()}")
print(f"pop_last(): {ll.pop_last()}")
print(f"Sonuç: {ll}")

print(f"\nİterasyon:")
for item in ll:
    print(f"  → {item}")
Çıktı bekleniyor...

📊 Ne Zaman Ne Kullanmalı?

İhtiyaç Kullan Neden?
Index ile erişim list O(1) random access
Başa ekleme/silme deque O(1) vs O(n)
Queue/Stack deque İki uçtan O(1)
Circular buffer deque(maxlen=n) Otomatik boyut limiti
Özel linked list Kendi sınıfın Eğitim/Özel ihtiyaç