Şu recursive fonksiyonları iterative yapma takıntısı bazen gerçekten işkenceye dönüşüyor. Bir ağaç yapısını (tree traversal) dolaşmak için yazdığım şık, 5 satırlık recursive fonksiyon vardı. "Stack overflow riski var, performans!" diye kendi kendimi kışkırttım ve iterative yapmaya karar verdim. Meğerse kendi mezarımı kazıyormuşum.
Recursive'te fonksiyon call stack'i hallederken, iterative versiyonda ben elle bir stack veya queue yönetmek zorunda kaldım. O şık mantık, bir sürü while</B> döngüsü, pop()</B], append()</B] ve visited</B] kontrolü arasında kayboldu. Kodu iki hafta sonra açıp baktığımda "Bunu ben mi yazdım?" dedirtti resmen. İşte o kıyaslamayı görmek için küçük bir kesit:
Python:
# Recursive (Temiz)
def dfs(node):
if not node:
return
print(node.val)
dfs(node.left)
dfs(node.right)
# Iterative (Stack ile cebelleşme)
def dfs_iterative(root):
stack = [root]
visited = set()
while stack:
node = stack.pop()
if node and node not in visited:
visited.add(node)
print(node.val)
stack.append(node.right)
stack.append(node.left)
Gördüğünüz gibi, ikinci versiyon ne yaptığını anlamak için beyninizi iki kat fazla yoruyor. Performans kazanımı mikro saniyeler için, okunabilirlikten oluyorsunuz.
Artık şu kurala uymaya çalışıyorum: Eğer diliniz (Python gibi) recursion depth limiti ciddi bir sorun değilse ve veri yapınız (örneğin, dengeli bir ağaç) çok derin değilse, recursive</B] kalmak çoğu zaman daha iyi. Okunabilirlik her şeyden önce gelir. Tabii, gerçekten derin bir recursion veya tail recursion optimization şansınız varsa, iterative düşünmek şart.
Siz de böyle "performans için okunabilirliği feda ettiğim" anlar oldu mu? Ya da bu stack yönetimini daha temiz yapmanın bir yolu var mı? Fikirlerinizi bekliyorum, yoksa tekrar recursive bir fonksiyon yazıp kendimi kaybedeceğim.