Pratik Yaparak Öğrenin
Bir BST'nin yüksekliğini (height) bulan fonksiyon yazın. Yükseklik, kökten en derin yaprağa olan kenar sayısıdır.
class Node:
def __init__(self, data):
self.data = data
self.left = None
self.right = None
def height(node):
"""
BST yüksekliğini bul - O(n)
Her node'u bir kez ziyaret etmemiz gerekir
"""
# Base case: Boş node
if node is None:
return -1 # Boş ağacın yüksekliği -1
# Recursive: Sol ve sağ alt ağaçların yüksekliği
left_height = height(node.left)
right_height = height(node.right)
# Maksimum + 1 (bu node için)
return 1 + max(left_height, right_height)
# Test
root = Node(50)
root.left = Node(30)
root.right = Node(70)
root.left.left = Node(20)
root.left.right = Node(40)
print("🌳 Ağaç yapısı:")
print(" 50")
print(" / \\")
print(" 30 70")
print(" / \\")
print(" 20 40")
print()
print(f"Yükseklik: {height(root)}") # 2
# Daha derin ağaç test et
root.left.left.left = Node(10)
print(f"\n10 eklendi → Yeni yükseklik: {height(root)}") # 3
BST'deki minimum ve maksimum değerleri bulan fonksiyonlar yazın.
class Node:
def __init__(self, data):
self.data = data
self.left = None
self.right = None
def find_min(node):
"""
BST'deki minimum değer - O(h)
Her zaman sola git!
"""
if node is None:
return None
current = node
while current.left:
current = current.left
return current.data
def find_max(node):
"""
BST'deki maksimum değer - O(h)
Her zaman sağa git!
"""
if node is None:
return None
current = node
while current.right:
current = current.right
return current.data
# Recursive versiyonlar
def find_min_recursive(node):
if node is None:
return None
if node.left is None:
return node.data
return find_min_recursive(node.left)
def find_max_recursive(node):
if node is None:
return None
if node.right is None:
return node.data
return find_max_recursive(node.right)
# Test
root = Node(50)
root.left = Node(30)
root.right = Node(70)
root.left.left = Node(20)
root.left.right = Node(40)
root.right.left = Node(60)
root.right.right = Node(80)
print("🌳 Ağaç: [50, 30, 70, 20, 40, 60, 80]")
print()
print(f"Minimum (iteratif): {find_min(root)}")
print(f"Maksimum (iteratif): {find_max(root)}")
print()
print(f"Minimum (recursive): {find_min_recursive(root)}")
print(f"Maksimum (recursive): {find_max_recursive(root)}")
Verilen bir binary tree'nin geçerli bir BST olup olmadığını kontrol eden fonksiyon yazın.
class Node:
def __init__(self, data):
self.data = data
self.left = None
self.right = None
def is_valid_bst_inorder(root):
"""
Yöntem 1: Inorder traversal ile kontrol
BST ise → inorder çıktı kesinlikle sıralı!
"""
result = []
def inorder(node):
if node:
inorder(node.left)
result.append(node.data)
inorder(node.right)
inorder(root)
# Sıralı mı kontrol et
for i in range(1, len(result)):
if result[i] <= result[i-1]:
return False
return True
def is_valid_bst_bounds(node, min_val=float('-inf'), max_val=float('inf')):
"""
Yöntem 2: Min/Max sınırları ile kontrol
Her node belirli bir aralıkta olmalı!
"""
if node is None:
return True
# Bu node sınırlar içinde mi?
if node.data <= min_val or node.data >= max_val:
return False
# Sol: max sınır = bu node'un değeri
# Sağ: min sınır = bu node'un değeri
return (is_valid_bst_bounds(node.left, min_val, node.data) and
is_valid_bst_bounds(node.right, node.data, max_val))
# Test 1: Geçerli BST
print("=" * 50)
print("Test 1: Geçerli BST")
print("=" * 50)
root1 = Node(50)
root1.left = Node(30)
root1.right = Node(70)
root1.left.left = Node(20)
root1.left.right = Node(40)
print(f"Inorder yöntemi: {is_valid_bst_inorder(root1)}")
print(f"Bounds yöntemi: {is_valid_bst_bounds(root1)}")
# Test 2: Geçersiz BST (sol çocuk > kök)
print("\n" + "=" * 50)
print("Test 2: Geçersiz BST (sol > kök)")
print("=" * 50)
root2 = Node(50)
root2.left = Node(60) # YANLIŞ! 60 > 50
root2.right = Node(70)
print(f"Inorder yöntemi: {is_valid_bst_inorder(root2)}")
print(f"Bounds yöntemi: {is_valid_bst_bounds(root2)}")
# Test 3: Karmaşık geçersiz BST
print("\n" + "=" * 50)
print("Test 3: Gizli hata (sol alt ağaçta büyük değer)")
print("=" * 50)
# 50
# / \
# 30 70
# / \
# 20 60 ← 60 > 50, BST kuralı ihlali!
root3 = Node(50)
root3.left = Node(30)
root3.right = Node(70)
root3.left.left = Node(20)
root3.left.right = Node(60) # YANLIŞ!
print(f"Inorder yöntemi: {is_valid_bst_inorder(root3)}")
print(f"Bounds yöntemi: {is_valid_bst_bounds(root3)}")
BST'deki k'ıncı en küçük elemanı bulan fonksiyon yazın.
class Node:
def __init__(self, data):
self.data = data
self.left = None
self.right = None
def kth_smallest(root, k):
"""
k'ıncı en küçük eleman - O(n)
Inorder traversal ile
"""
result = []
def inorder(node):
if node and len(result) < k: # Optimizasyon: k eleman yeterli
inorder(node.left)
result.append(node.data)
inorder(node.right)
inorder(root)
if k <= len(result):
return result[k-1]
return None
def kth_smallest_iterative(root, k):
"""
k'ıncı en küçük eleman - O(h + k)
Stack ile iteratif inorder - daha verimli!
"""
stack = []
current = root
count = 0
while stack or current:
# En sola git
while current:
stack.append(current)
current = current.left
# Backtrack
current = stack.pop()
count += 1
if count == k:
return current.data
current = current.right
return None
# Test
root = Node(50)
root.left = Node(30)
root.right = Node(70)
root.left.left = Node(20)
root.left.right = Node(40)
root.right.left = Node(60)
root.right.right = Node(80)
print("🌳 Ağaç: [50, 30, 70, 20, 40, 60, 80]")
print("📋 Sıralı: [20, 30, 40, 50, 60, 70, 80]")
print()
for k in [1, 3, 5, 7]:
result = kth_smallest(root, k)
print(f"{k}. en küçük: {result}")
BST'de iki node'un en yakın ortak atasını (LCA) bulan fonksiyon yazın.
class Node:
def __init__(self, data):
self.data = data
self.left = None
self.right = None
def lca(root, p, q):
"""
Lowest Common Ancestor - O(h)
BST özelliğini kullan!
"""
current = root
while current:
# İkisi de solda
if p < current.data and q < current.data:
current = current.left
# İkisi de sağda
elif p > current.data and q > current.data:
current = current.right
# Biri solda, biri sağda (veya biri current)
else:
return current.data
return None
def lca_recursive(root, p, q):
"""Recursive versiyon"""
if root is None:
return None
if p < root.data and q < root.data:
return lca_recursive(root.left, p, q)
elif p > root.data and q > root.data:
return lca_recursive(root.right, p, q)
else:
return root.data
# Test
root = Node(50)
root.left = Node(30)
root.right = Node(70)
root.left.left = Node(20)
root.left.right = Node(40)
root.right.left = Node(60)
root.right.right = Node(80)
print("🌳 Ağaç yapısı:")
print(" 50")
print(" / \\")
print(" 30 70")
print(" / \\ / \\")
print(" 20 40 60 80")
print()
test_cases = [(20, 40), (20, 80), (60, 80), (30, 70)]
for p, q in test_cases:
result = lca(root, p, q)
print(f"LCA({p}, {q}) = {result}")