Graf Teorisi

Ağlar, bağlantılar ve algoritmaların matematiksel dünyası

G = (V, E) // Graf = (Düğümler, Kenarlar)

Graf Nedir?

Graf teorisi, matematikte nesneler arasındaki ilişkileri modellemek için kullanılan bir daldır. Graf, düğümler (vertices/nodes) ve bu düğümleri birbirine bağlayan kenarlardan (edges) oluşan bir matematiksel yapıdır.

G = (V, E)

Burada V düğüm kümesini, E ise kenar kümesini temsil eder. Graf teorisi, ağ analizi, bilgisayar bilimi, sosyoloji, biyoloji ve birçok alanda uygulama bulur.

A
B
C
D
Graf Teorisinin Uygulama Alanları:
  • • Sosyal medya ağları analizi
  • • Ulaşım ve lojistik optimizasyonu
  • • İnternet ve web sayfası yapısı
  • • Moleküler yapı analizi
  • • Bilgisayar ağları ve güvenlik
  • • Oyun teorisi ve strateji
Tarihçe
Graf teorisi, 1736'da Leonhard Euler'in Königsberg köprüleri problemini çözmesiyle başladı. Bu problem, günümüz graf teorisinin temelini atan ilk çalışma olarak kabul edilir.

Modern bilgisayar biliminde graf teorisi, algoritma tasarımı, veri yapıları ve karmaşıklık analizinin temelini oluşturur. Günlük hayatta GPS navigasyon, sosyal medya algoritmaları ve arama motorları gibi teknolojilerde kullanılır.

Graf Türleri

Graflar, yapısal özelliklerine göre farklı türlere ayrılır. Her graf türü, belirli problem tiplerini çözmek için uygundur ve farklı algoritmaların kullanılmasını gerektirir.

Yönlü ve Yönsüz Graflar:

Yönsüz Graf (Undirected Graph): Kenarların yönü yoktur. A-B kenarı, B-A kenarı ile aynıdır.

Yönlü Graf (Directed Graph/Digraph): Kenarların belirli bir yönü vardır. A→B kenarı, B→A kenarından farklıdır.

Ağırlıklı Graflar:

// Ağırlıklı graf örneği
Graf G = {
    "A": [("B", 5), ("C", 3)],
    "B": [("D", 7)],
    "C": [("D", 2)]
}
Ağırlık Türleri
Mesafe: Fiziksel uzaklık (km, mil)
Maliyet: Para birimi, zaman
Kapasite: Bant genişliği, trafik kapasitesi
Olasılık: Bağlantı güvenilirliği

Özel Graf Türleri:

Tam Graf (Complete Graph): Her düğüm diğer tüm düğümlerle bağlıdır. n düğümlü tam grafta n(n-1)/2 kenar vardır.

Ağaç (Tree): n düğümlü, n-1 kenarlı, döngüsüz bağlantılı graf.

DAG (Directed Acyclic Graph): Yönlü ve döngüsüz graf.

Bipartite Graf: Düğümler iki gruba ayrılabilir ve kenarlar sadece gruplar arası bağlantı sağlar.
💡 Seçim Kriteri: Problem türüne göre graf seçimi kritiktir. Yol bulma için ağırlıklı graf, sosyal ağ analizi için yönsüz graf, proje planlama için DAG tercih edilir.

Temel Kavramlar ve Terminoloji

Graf teorisinde kullanılan temel kavramları anlamak, algoritmaları öğrenmek ve uygulamak için hayati önem taşır.

Temel Tanımlar:
  • Derece (Degree): Bir düğüme bağlı kenar sayısı
  • Yol (Path): Düğümler arası bağlantı dizisi
  • Döngü (Cycle): Başladığı noktaya dönen yol
  • Bağlantılılık: Düğümler arası erişilebilirlik
  • Bileşen: Birbirine bağlı düğüm alt kümesi

Derece Kavramı:

deg(v) = |{u ∈ V : (u,v) ∈ E}|
Derece Hesaplama
Yönsüz grafta: Bağlı kenar sayısı
Yönlü grafta: Gelen derece + Giden derece
Toplam derece: Her zaman çift sayıdır (Handshaking Lemma)

Yol ve Döngü:

  1. Basit Yol: Hiçbir düğüm tekrarlanmaz
  2. Basit Döngü: Başlangıç hariç hiçbir düğüm tekrarlanmaz
  3. Hamilton Yolu: Her düğümü tam bir kez ziyaret eder
  4. Euler Yolu: Her kenarı tam bir kez kullanır
Dikkat: Hamilton ve Euler problemleri NP-complete/NP-hard kategorisindedir. Büyük graflar için polinom zamanda çözüm bulunması zordur.

Graf Özellikleri:

Yoğunluk (Density): |E| / |V|(|V|-1)/2
Çap (Diameter): En uzun en kısa yol
Yarıçap (Radius): En kısa maksimum uzaklık
Merkezilik: Düğümün ağdaki önemi

Graf Gösterimi ve Veri Yapıları

Grafların bilgisayar belleğinde nasıl saklanacağı, algoritmaların verimliliğini doğrudan etkiler. Üç ana gösterim yöntemi vardır.

1. Komşuluk Matrisi (Adjacency Matrix):

// n×n matrix, A[i][j] = 1 eğer (i,j) kenarı varsa
Matrix A = {
    //   A  B  C  D
    A: [ 0, 1, 1, 0 ],  // A düğümü
    B: [ 1, 0, 0, 1 ],  // B düğümü
    C: [ 1, 0, 0, 1 ],  // C düğümü
    D: [ 0, 1, 1, 0 ]   // D düğümü
}
Zaman Karmaşıklığı:
• Kenar kontrolü: O(1)
• Kenar ekleme/silme: O(1)
• Komşu bulma: O(V)

Alan Karmaşıklığı: O(V²)

2. Komşuluk Listesi (Adjacency List):

// Her düğüm için komşularının listesi
AdjList = {
    "A": ["B", "C"],
    "B": ["A", "D"],
    "C": ["A", "D"],
    "D": ["B", "C"]
}
Zaman Karmaşıklığı:
• Kenar kontrolü: O(deg(v))
• Kenar ekleme: O(1)
• Komşu bulma: O(deg(v))

Alan Karmaşıklığı: O(V + E)

3. Kenar Listesi (Edge List):

// Tüm kenarların listesi
EdgeList = [
    ("A", "B"),
    ("A", "C"),
    ("B", "D"),
    ("C", "D")
]
💡 Hangisini Seçmeli:
• Sık kenar sorgusu: Komşuluk matrisi
• Seyrek graf: Komşuluk listesi
• Kenar işlemleri: Kenar listesi
• Bellek kısıtı: Komşuluk listesi
Bellek Kullanımı Karşılaştırması
1000 düğümlü, 5000 kenarlı graf için:
• Matris: ~1MB (1000²)
• Liste: ~40KB (1000 + 2×5000)
• Kenar listesi: ~40KB (2×5000)

Graf Gezinme Algoritmaları

Graf gezinme algoritmaları, graf üzerindeki tüm erişilebilir düğümleri sistematik olarak ziyaret etmek için kullanılır. İki temel yaklaşım vardır: Derinlik İlk Arama (DFS) ve Genişlik İlk Arama (BFS).

Gezinme Algoritması Kullanım Alanları:
  • • Bağlantılılık kontrolü
  • • Döngü tespiti
  • • Topolojik sıralama
  • • En kısa yol bulma
  • • Güçlü bağlantılı bileşenler
Önemli Not: Her iki algoritma da O(V + E) zaman karmaşıklığına sahiptir, ancak kullanım alanları farklıdır.

Derinlik İlk Arama (DFS)

DFS, bir düğümden başlayarak mümkün olduğunca derine iner, geri dönüş yapar ve diğer dalları keşfeder. Stack veri yapısını (özyinelemeli veya açık) kullanır.

  1. Başlangıç düğümünü ziyaret et ve işaretle
  2. Ziyaret edilmemiş komşu düğüm varsa, oraya git (adım 1'i tekrarla)
  3. Ziyaret edilmemiş komşu yoksa, geri dön
  4. Tüm erişilebilir düğümler ziyaret edilene kadar devam et
function DFS(graf, başlangıç):
    visited = new Set()
    stack = [başlangıç]
    
    while stack is not empty:
        düğüm = stack.pop()
        
        if düğüm not in visited:
            visited.add(düğüm)
            process(düğüm)  // Düğümü işle
            
            for komşu in graf[düğüm]:
                if komşu not in visited:
                    stack.append(komşu)
Zaman Karmaşıklığı: O(V + E)
Alan Karmaşıklığı: O(V) - stack için
Özyinelemeli versiyon: O(V) - call stack
DFS Ağacı
DFS sırasında kullanılan kenarlar DFS ağacını oluşturur. Diğer kenarlar:
• Back edge: Döngü göstergesi
• Forward edge: Torun bağlantısı
• Cross edge: Farklı dallar arası

DFS Uygulamaları:

💡 DFS İdeal Kullanım Alanları:
• Döngü tespiti: Back edge varlığı
• Topolojik sıralama: Bitirme zamanına göre
• Güçlü bağlantılı bileşenler: Kosaraju algoritması
• Labirent çözme: Bir yolu sonuna kadar takip
// Döngü tespiti için DFS
function hasCycle(graf):
    renk = {} // Beyaz=0, Gri=1, Siyah=2
    
    for düğüm in graf:
        if renk[düğüm] == 0:
            if dfsVisit(graf, düğüm, renk):
                return True
    return False

function dfsVisit(graf, düğüm, renk):
    renk[düğüm] = 1  // Gri (işleniyor)
    
    for komşu in graf[düğüm]:
        if renk[komşu] == 1:  // Back edge
            return True
        if renk[komşu] == 0 and dfsVisit(graf, komşu, renk):
            return True
    
    renk[düğüm] = 2  // Siyah (tamamlandı)
    return False

Genişlik İlk Arama (BFS)

BFS, başlangıç düğümünden katman katman genişleyerek ilerler. Önce tüm komşular, sonra komşuların komşuları ziyaret edilir. Queue veri yapısını kullanır.

  1. Başlangıç düğümünü kuyruğa ekle ve ziyaret et
  2. Kuyruktan düğüm çıkar
  3. Bu düğümün ziyaret edilmemiş komşularını kuyruğa ekle
  4. Kuyruk boşalana kadar 2-3 adımlarını tekrarla
function BFS(graf, başlangıç):
    visited = new Set()
    queue = new Queue()
    distance = {}
    
    queue.enqueue(başlangıç)
    visited.add(başlangıç)
    distance[başlangıç] = 0
    
    while queue is not empty:
        düğüm = queue.dequeue()
        process(düğüm)
        
        for komşu in graf[düğüm]:
            if komşu not in visited:
                visited.add(komşu)
                distance[komşu] = distance[düğüm] + 1
                queue.enqueue(komşu)
Zaman Karmaşıklığı: O(V + E)
Alan Karmaşıklığı: O(V) - queue için
Mesafe garantisi: En kısa yol (ağırlıksız graf)
BFS Katmanları
BFS, düğümleri başlangıçtan uzaklıklarına göre katmanlar halinde ziyaret eder:
• Katman 0: Başlangıç düğümü
• Katman 1: Doğrudan komşular
• Katman k: k uzaklıktaki düğümler

BFS Uygulamaları:

💡 BFS İdeal Kullanım Alanları:
• En kısa yol: Ağırlıksız graflarda
• Minimum adım problemi: Oyun çözme
• Seviye bazlı işlemler: Ağaç seviyesi
• Bağlantılılık testi: Erişilebilirlik kontrolü
// En kısa yol bulma (ağırlıksız graf)
function shortestPath(graf, başlangıç, hedef):
    if başlangıç == hedef:
        return [başlangıç]
    
    visited = new Set()
    queue = new Queue()
    parent = {}
    
    queue.enqueue(başlangıç)
    visited.add(başlangıç)
    parent[başlangıç] = null
    
    while queue is not empty:
        düğüm = queue.dequeue()
        
        for komşu in graf[düğüm]:
            if komşu not in visited:
                visited.add(komşu)
                parent[komşu] = düğüm
                queue.enqueue(komşu)
                
                if komşu == hedef:
                    return reconstructPath(parent, hedef)
    
    return null  // Yol bulunamadı
DFS vs BFS Seçimi: En kısa yol için BFS, bellek tasarrufu için DFS, döngü tespiti için DFS, seviye işlemleri için BFS tercih edilir.

En Kısa Yol Problemleri

En kısa yol problemleri, graf teorisinin en praktik uygulamalı alanlarından biridir. GPS navigasyon, ağ yönlendirme ve lojistik optimizasyonunda kritik öneme sahiptir.

En Kısa Yol Problem Türleri:
  • Tek Kaynak (Single Source): Bir düğümden diğer tüm düğümlere
  • Tek Hedef (Single Destination): Tüm düğümlerden bir hedefe
  • Tek Çift (Single Pair): Belirli iki düğüm arası
  • Tüm Çiftler (All Pairs): Her düğüm çifti arası

Algoritma Seçimi:

Ağırlıksız Graf: BFS - O(V + E)
Pozitif Ağırlık: Dijkstra - O(V² + E) veya O((V + E) log V)
Negatif Ağırlık: Bellman-Ford - O(VE)
Tüm Çiftler: Floyd-Warshall - O(V³)
Negatif Döngü Problemi
Negatif ağırlıklı döngü varsa, en kısa yol tanımsızdır çünkü döngüyü ne kadar çok dönerseniz toplam maliyet o kadar azalır.
Pratik İpucu: Gerçek uygulamalarda Dijkstra algoritması genellikle yeterlidir çünkü mesafe, zaman, maliyet gibi ağırlıklar doğal olarak pozitiftir.

Dijkstra Algoritması

Dijkstra algoritması, pozitif ağırlıklı graflarda tek kaynak en kısa yol problemini çözer. Greedy yaklaşım kullanarak optimal sonuç garanti eder.

  1. Tüm düğümlerin mesafesini ∞ olarak başlat (kaynak = 0)
  2. Ziyaret edilmemiş en kısa mesafeli düğümü seç
  3. Bu düğümün komşularının mesafelerini güncelle
  4. Düğümü ziyaret edildi olarak işaretle
  5. Tüm düğümler ziyaret edilene kadar 2-4 adımlarını tekrarla
function dijkstra(graf, kaynak):
    distance = {}
    visited = new Set()
    parent = {}
    priorityQueue = new MinHeap()
    
    // Başlangıç değerleri
    for düğüm in graf:
        distance[düğüm] = ∞
        parent[düğüm] = null
    
    distance[kaynak] = 0
    priorityQueue.insert((kaynak, 0))
    
    while priorityQueue is not empty:
        (düğüm, dist) = priorityQueue.extractMin()
        
        if düğüm in visited:
            continue
        
        visited.add(düğüm)
        
        for (komşu, ağırlık) in graf[düğüm]:
            newDistance = distance[düğüm] + ağırlık
            
            if newDistance < distance[komşu]:
                distance[komşu] = newDistance
                parent[komşu] = düğüm
                priorityQueue.insert((komşu, newDistance))
    
    return distance, parent
Binary Heap ile: O((V + E) log V)
Fibonacci Heap ile: O(E + V log V)
Basit dizi ile: O(V²)
Alan Karmaşıklığı: O(V)
Optimizasyon İpuçları
Erken durma: Hedefe ulaşınca dur
İki yönlü arama: Kaynak ve hedeften eş zamanlı
A* algoritması: Heuristik fonksiyon ekle
Potansiyel fonksiyonu: Johnson algoritması

Uygulama Örnekleri:

// Yol yeniden oluşturma
function getPath(parent, kaynak, hedef):
    if parent[hedef] == null and hedef != kaynak:
        return null  // Yol yok
    
    path = []
    current = hedef
    
    while current != null:
        path.prepend(current)
        current = parent[current]
    
    return path
Gerçek Dünya Uygulaması: GPS navigasyon sistemleri, ağ yönlendirme protokolleri (OSPF), oyun AI'ları (pathfinding), sosyal ağ analizi.

Minimum Spanning Tree (MST)

Minimum Spanning Tree, ağırlıklı bağlantılı bir grafın tüm düğümlerini en az maliyetle birbirine bağlayan ağaç yapısıdır. V düğümlü grafta V-1 kenar içerir ve döngü barındırmaz.

MST Özellikleri: |V| düğüm, |V|-1 kenar, döngüsüz, bağlantılı
MST Uygulamaları:
  • • Ağ tasarımı (elektrik, internet, su)
  • • Kümeleme algoritmalarında
  • • Devre tasarımında
  • • Yaklaşık TSP çözümünde

Kruskal Algoritması:

  1. Tüm kenarları ağırlığa göre artan sırada sırala
  2. En hafif kenardan başlayarak:
  3. Kenar döngü oluşturmuyorsa MST'ye ekle
  4. V-1 kenar seçilene kadar devam et
function kruskal(graf):
    mst = []
    edges = getAllEdges(graf)
    edges.sort()  // Ağırlığa göre sırala
    
    unionFind = new UnionFind(graf.vertices)
    
    for (u, v, weight) in edges:
        if unionFind.find(u) != unionFind.find(v):
            mst.append((u, v, weight))
            unionFind.union(u, v)
            
            if mst.length == |V| - 1:
                break
    
    return mst

Prim Algoritması:

  1. Rastgele bir düğümle başla
  2. MST'ye bağlı en hafif kenarı seç
  3. Yeni düğümü MST'ye ekle
  4. Tüm düğümler eklenene kadar 2-3 adımlarını tekrarla
function prim(graf, start):
    mst = []
    visited = new Set([start])
    priorityQueue = new MinHeap()
    
    // Başlangıç düğümünün kenarlarını ekle
    for (neighbor, weight) in graf[start]:
        priorityQueue.insert((weight, start, neighbor))
    
    while priorityQueue is not empty and visited.size < |V|:
        (weight, u, v) = priorityQueue.extractMin()
        
        if v in visited:
            continue
        
        mst.append((u, v, weight))
        visited.add(v)
        
        for (neighbor, edgeWeight) in graf[v]:
            if neighbor not in visited:
                priorityQueue.insert((edgeWeight, v, neighbor))
    
    return mst
Kruskal: O(E log E) - sıralama dominates
Prim (Binary Heap): O((V + E) log V)
Prim (Fibonacci Heap): O(E + V log V)
Alan: Her ikisi de O(V)
Kruskal vs Prim
Kruskal: Seyrek graflar için ideal, kenar odaklı
Prim: Yoğun graflar için ideal, düğüm odaklı
Her ikisi de: Optimal sonuç garanti eder

Topolojik Sıralama

Topolojik sıralama, yönlü asiklik graflarda (DAG) düğümlerin, her kenar (u,v) için u'nun v'den önce geldiği doğrusal bir sıralamasıdır. Öncelik bağımlılıklarının çözümünde kritiktir.

Topolojik Sıralama Uygulamaları:
  • • Proje görev sıralaması
  • • Ders önkoşul sistemi
  • • Makefile bağımlılıkları
  • • Spreadsheet formül hesaplama
  • • İş akışı yönetimi

Kahn Algoritması (BFS Tabanlı):

  1. Her düğümün gelen derece sayısını hesapla
  2. Gelen derecesi 0 olan düğümleri kuyruğa ekle
  3. Kuyruktan düğüm çıkar ve sonuca ekle
  4. Bu düğümün komşularının gelen derecelerini azalt
  5. Gelen derecesi 0 olanları kuyruğa ekle
  6. Kuyruk boşalana kadar 3-5 adımlarını tekrarla
function topologicalSort(graf):
    inDegree = {}
    result = []
    queue = new Queue()
    
    // Gelen dereceleri hesapla
    for düğüm in graf:
        inDegree[düğüm] = 0
    
    for düğüm in graf:
        for komşu in graf[düğüm]:
            inDegree[komşu]++
    
    // Gelen derecesi 0 olanları bul
    for düğüm in graf:
        if inDegree[düğüm] == 0:
            queue.enqueue(düğüm)
    
    while queue is not empty:
        düğüm = queue.dequeue()
        result.append(düğüm)
        
        for komşu in graf[düğüm]:
            inDegree[komşu]--
            if inDegree[komşu] == 0:
                queue.enqueue(komşu)
    
    if result.length != |V|:
        return null  // Döngü var
    
    return result

DFS Tabanlı Yaklaşım:

function topologicalSortDFS(graf):
    visited = new Set()
    stack = []
    
    for düğüm in graf:
        if düğüm not in visited:
            dfsVisit(graf, düğüm, visited, stack)
    
    return stack.reverse()

function dfsVisit(graf, düğüm, visited, stack):
    visited.add(düğüm)
    
    for komşu in graf[düğüm]:
        if komşu not in visited:
            dfsVisit(graf, komşu, visited, stack)
    
    stack.append(düğüm)  // Bitirme sırasına göre
Kahn Algoritması: O(V + E)
DFS Tabanlı: O(V + E)
Alan Karmaşıklığı: O(V)
Döngü Tespiti: Her ikisi de destekler
Önemli: Topolojik sıralama sadece DAG'larda (Directed Acyclic Graph) mümkündür. Döngü varsa sıralama yapılamaz.
Praktik Örnek
Üniversite ders sistemi: "Algoritma" dersi için "Veri Yapıları" ön koşuldur. "Veri Yapıları" için de "Programlama" ön koşuldur. Topolojik sıralama: Programlama → Veri Yapıları → Algoritma

Graf Teorisinin Uygulama Alanları

Graf teorisi, modern teknoloji ve bilimin birçok alanında temel bir araçtır. Sosyal ağlardan biyoinformatiğe, ulaştırmadan yapay zekaya kadar geniş bir yelpazede kullanılır.

Bilgisayar Ağları:

Ağ Protokolleri:
  • • OSPF: En kısa yol yönlendirme
  • • BGP: İnternet omurga yönlendirme
  • • STP: Köprü döngü önleme
  • • Load Balancing: Trafik dağıtımı

Sosyal Ağ Analizi:

Sosyal Ağ Metrikleri
Derece Merkeziliği: Bağlantı sayısı
Betweenness: Köprü rolü
Closeness: Diğerlerine yakınlık
PageRank: Önem puanı

Biyoinformatik:

Protein Etkileşim Ağları: Protein-protein etkileşimlerinin modellenmesi
Gen Düzenleme Ağları: Gen ekspresyon kontrolü
Metabolik Yolaklar: Biyokimyasal reaksiyon zincirleri
Filogenetik Ağaçlar: Evrimsel ilişkiler

Oyun ve AI:

// Oyun haritasında pathfinding
function gamePathfinding(harita, başlangıç, hedef):
    // A* algoritması ile heuristik arama
    openSet = new PriorityQueue()
    closedSet = new Set()
    
    gScore = {başlangıç: 0}
    fScore = {başlangıç: heuristic(başlangıç, hedef)}
    
    openSet.enqueue((fScore[başlangıç], başlangıç))
    
    while openSet is not empty:
        current = openSet.dequeue().second
        
        if current == hedef:
            return reconstructPath(current)
        
        closedSet.add(current)
        
        for komşu in getNeighbors(current):
            if komşu in closedSet:
                continue
            
            tentativeG = gScore[current] + distance(current, komşu)
            
            if tentativeG < gScore.get(komşu, ∞):
                gScore[komşu] = tentativeG
                fScore[komşu] = tentativeG + heuristic(komşu, hedef)
                openSet.enqueue((fScore[komşu], komşu))

Makine Öğrenmesi:

Graf Neural Networks (GNN):
• GraphSAGE: Büyük graflar için örnekleme
• GCN: Graf konvolüsyonel ağlar
• GraphTransformer: Attention mekanizması
• Knowledge Graphs: Bilgi representation

Finansal Sistemler:

Risk Analizi ve Fraud Detection:
  • • Transaction Networks: Şüpheli para transferleri
  • • Credit Risk: Borç verme ağları
  • • Market Analysis: Şirket ilişki ağları
  • • Algorithmic Trading: Piyasa korelasyonları

Ulaştırma ve Lojistik:

Araç Rotalama Problemi (VRP): Çoklu araç optimizasyonu
Kapasiteli Ağ Tasarımı: Trafik akış optimizasyonu
Hub Location: Merkez lokasyon seçimi
Last Mile Delivery: Son kilometre dağıtım
Gerçek Dünya Örneği
Amazon'un dağıtım ağı, Uber'in sürücü-yolcu eşleştirmesi, Google Maps'in rota optimizasyonu - hepsi graf teorisi algoritmalarına dayanır.

Gelecek Trendler:

Emerging Areas:
• Quantum Graphs: Kuantum hesaplama uygulamaları
• Dynamic Graphs: Zamanla değişen ağlar
• Multilayer Networks: Çok katmanlı graf analizi
• Graph Databases: Neo4j, Amazon Neptune

İleri Düzey Graf Algoritmaları

Graf teorisinin daha karmaşık problemleri için geliştirilmiş algoritmalar ve teknikler.

Network Flow:
• Max Flow Min Cut: Ford-Fulkerson, Edmonds-Karp
• Min Cost Flow: Maliyet optimizasyonu
• Multi-commodity Flow: Çoklu kaynak-hedef

Matching Problems:
• Maximum Bipartite Matching: Hungarian algoritması
• Stable Marriage: Gale-Shapley
• Maximum Weight Matching: Blossom algoritması
Karmaşıklık Sınıfları:
• P: Polinom zamanda çözülebilir
• NP: Non-deterministic polinom
• NP-Complete: Hamilton Path, TSP
• NP-Hard: Approximation algoritmaları gerekli

Performans Optimizasyonu ve Pratik İpuçları

Büyük ölçekli graf problemlerinde performans kritiktir. Doğru veri yapısı ve algoritma seçimi önemlidir.

Büyük Graf Optimizasyonları:
  • • Parallelization: Multi-threading, GPU
  • • Approximation: Heuristic yaklaşımlar
  • • Sampling: Monte Carlo yöntemleri
  • • Preprocessing: Graf sıkıştırma
  • • Caching: Sonuç önbellekleme
Bellek Yönetimi
Büyük graflar için:
• Komşuluk listesi kullanın (seyrek graflar)
• Bit manipulation (boolean operasyonlar)
• Streaming algorithms (sınırlı bellek)
• External memory algorithms (disk tabanlı)
Yaygın Hatalar:
• Yanlış veri yapısı seçimi
• Gereksiz graf kopyalama
• Etkisiz döngü tespiti
• Bellek sızıntıları (memory leaks)

Graf Teorisi Yolculuğunuz Başlasın!

Graf teorisi, modern bilgisayar biliminin temel taşlarından biridir. Bu kapsamlı rehberle algoritmaları anladınız, uygulamaları keşfettiniz.

Öğrenmeyi Sürdürme Tavsiyeleri
Pratik yapın: LeetCode, HackerRank graf problemleri çözün
Projeler geliştirin: Sosyal ağ analizi, pathfinding oyunu
Kütüphaneler öğrenin: NetworkX (Python), JGraphT (Java)
İleri konular: Graph Neural Networks, Quantum graphs
Topluluk: Akademik makaleler, konferanslar takip edin
Önemli Kaynaklar:
• Kitaplar: "Introduction to Algorithms" (CLRS)
• Online: Coursera Graph Theory courses
• Visualizer: Graph Online, D3.js
• Implementasyon: GitHub graph algorithm repos

"Bağlantıların gücünü keşfedin!" 🚀

Graf teorisi ile problemleri çözme yetkiniz artık gelişti. Algoritmaları uygulayın, ağları analiz edin!