Neden Hazır Yapıları Sarmalamalıyız?
Python listeleri hafızada bitişik (contiguous) durur. Bu, C'deki dizilere benzer bir yapıdır.
pop(0) ile en baştan eleman silerseniz, geriye kalan TÜM elemanlar bir adım sola kaymak zorundadır.
Sonuç: list.pop(0) → O(n) zaman karmaşıklığı
Deque (Double Ended Queue), iki ucu açık boru gibidir. İçeride doubly linked list benzeri bir yapı kullanır.
Hem baştan hem sondan ekleme/çıkarma işlemleri O(1) sabit zamanda gerçekleşir.
deque hem Stack hem Queue gibi kullanılabilir, ama bu tehlikelidir:
Veri yapısı kuralları ihlal edildi! Queue FIFO olmalı, ama kullanıcı LIFO işlemi yaptı.
Kullanıcıya sadece izin verilen metodları sunarak veri yapısı kurallarını zorla:
enqueue() ve dequeue()push() ve pop()from collections import deque
class Queue:
"""
FIFO (First In, First Out) Queue implementasyonu.
Sadece izin verilen metodları sunar.
"""
def __init__(self):
self._data = deque()
def enqueue(self, item):
"""Kuyruğun sonuna eleman ekler"""
self._data.append(item)
print(f"✅ Eklendi: {item} → Kuyruk: {list(self._data)}")
def dequeue(self):
"""Kuyruğun başından eleman çıkarır"""
if self.is_empty():
raise IndexError("Kuyruk boş!")
item = self._data.popleft()
print(f"🔴 Çıkarıldı: {item} ← Kuyruk: {list(self._data)}")
return item
def peek(self):
"""Baştaki elemana bakar (çıkarmaz)"""
if self.is_empty():
return None
return self._data[0]
def is_empty(self):
return len(self._data) == 0
def __len__(self):
return len(self._data)
# Test edelim
print("=" * 40)
print("🚀 Queue Wrapper Testi")
print("=" * 40)
q = Queue()
q.enqueue("Müşteri 1")
q.enqueue("Müşteri 2")
q.enqueue("Müşteri 3")
print(f"\n📌 Sıradaki: {q.peek()}")
print(f"📊 Kuyruk uzunluğu: {len(q)}")
print("\n--- Sıra işleniyor ---")
while not q.is_empty():
q.dequeue()
Aynı deque'yi Stack için de kullanabiliriz, ama farklı metodlar sunarız:
from collections import deque
class Stack:
"""
LIFO (Last In, First Out) Stack implementasyonu.
Sadece izin verilen metodları sunar.
"""
def __init__(self):
self._data = deque()
def push(self, item):
"""Yığının tepesine eleman ekler"""
self._data.append(item)
print(f"📥 Push: {item} → Stack: {list(self._data)}")
def pop(self):
"""Yığının tepesinden eleman çıkarır"""
if self.is_empty():
raise IndexError("Stack boş!")
item = self._data.pop()
print(f"📤 Pop: {item} ← Stack: {list(self._data)}")
return item
def top(self):
"""Tepedeki elemana bakar (çıkarmaz)"""
if self.is_empty():
return None
return self._data[-1]
def is_empty(self):
return len(self._data) == 0
def __len__(self):
return len(self._data)
# Test edelim
print("=" * 40)
print("📚 Stack Wrapper Testi")
print("=" * 40)
s = Stack()
s.push("Tabak 1")
s.push("Tabak 2")
s.push("Tabak 3")
print(f"\n📌 Tepedeki: {s.top()}")
print(f"📊 Stack uzunluğu: {len(s)}")
print("\n--- Tabaklar alınıyor (LIFO) ---")
while not s.is_empty():
s.pop()
10,000 elemanı baştan silme yarışı. List neden kaybedecek?
import time
from collections import deque
N = 10000 # Eleman sayısı
print("=" * 50)
print(f"🏁 PERFORMANS YARIŞI: {N:,} eleman baştan silme")
print("=" * 50)
# --- LIST TESTİ ---
print("\n📋 List testi başlıyor...")
test_list = list(range(N))
start = time.time()
while test_list:
test_list.pop(0) # O(n) - her silmede kaydırma!
list_time = time.time() - start
print(f"⏱️ List süresi: {list_time:.4f} saniye")
# --- DEQUE TESTİ ---
print("\n🔗 Deque testi başlıyor...")
test_deque = deque(range(N))
start = time.time()
while test_deque:
test_deque.popleft() # O(1) - sabit zaman!
deque_time = time.time() - start
print(f"⏱️ Deque süresi: {deque_time:.4f} saniye")
# --- SONUÇLAR ---
print("\n" + "=" * 50)
print("📊 SONUÇLAR")
print("=" * 50)
if list_time > 0 and deque_time > 0:
hiz_farki = list_time / deque_time
print(f"🐢 List: {list_time:.4f} saniye")
print(f"🚀 Deque: {deque_time:.4f} saniye")
print(f"\n✨ Deque, List'ten {hiz_farki:.1f}x daha hızlı!")
print(f"\n💡 Neden? List O(n), Deque O(1) karmaşıklık!")