Bölüm 11: Çizgeler

Veri Yapıları
Temel kavramlarDerece, yol, döngüKomşuluk listesi ve matrisi BFSDFSAğırlıksız en kısa yolDijkstra
Sercan KÜLCÜ · Giresun Üniversitesi · Bilgisayar Mühendisliği

Giriş

Öğrenme Çıktıları

Temel kavramlar

Düğüm, kenar, yön, ağırlık, yol ve bağlılık kavramlarını açıklamak.

Gösterimler

Komşuluk matrisi ile komşuluk listesini maliyetleriyle karşılaştırmak.

Gezinmeler

BFS ve DFS algoritmalarını uygulayıp sonuçlarını yorumlamak.

En kısa yol

Ağırlıksız BFS ve Dijkstra algoritması için uygun problem türünü seçmek.

Temel Kavramlar

Çizge (Graph)

  • Düğümlerin (vertex / node) ve bu düğümleri birbirine bağlayan kenarların (edge) bir araya gelmesiyle oluşur.
  • Karmaşık ilişkileri, ağları ve yapıları temsil etmek için kullanılır.
  • Çizge teorisi, düğümler ve kenarlar arasındaki ilişkileri inceler.
0 1 2 3 4 kenar düğüm
Bir çizge G = (V, E) ikilisidir: V düğümler kümesi, E kenarlar kümesi.
Örnek: V = {0, 1, 2, 3, 4}, E = {(0,1), (0,4), (1,2), (1,3), (1,4), (2,3), (3,4)} · n = |V| = 5, m = |E| = 7
Ağaç ile farkıKök yoktur, döngü olabilir, bir düğüme birden çok yoldan ulaşılabilir.
Bölüm 1'den hatırlaÇizge "birçoğa-birçok" ilişkiyi modeller.
NotasyonBu bölümde n = düğüm sayısı, m = kenar sayısı.

Temel Kavramlar

Düğüm (Vertex, Node)

  • Çizgenin temel yapı taşıdır.
  • Şehirler, kişiler, bilgisayarlar gibi nesneleri temsil eder.
  • Düğüm, bir değer (etiket, ad, konum…) saklayabilir.
  • Örnek: haritadaki şehirler ve kavşaklar.
Türkiye karayolları haritası: şehirler düğüm, aralarındaki yollar kenar olarak düşünülebilir.

Karayolu haritası: şehirler düğüm, yollar kenar

Harita çizge olarak modellenince "İstanbul'dan Van'a en kısa yol hangisi?" sorusu bir çizge algoritması problemine dönüşür (bölümün sonunda: Dijkstra).

Temel Kavramlar

Kenar (Edge)

  • Düğümleri birbirine bağlayan bağlantılardır.
  • Kenarlar düğümler arasındaki ilişkiyi temsil eder.
  • (v, w) bir kenar ise v ve w bitişik (komşu, adjacent) düğümlerdir; kenar bu iki düğüme bağlıdır (incident).
  • Örnek: şehirler arasındaki yollar, bilgisayar ağındaki bağlantılar, sosyal ağdaki arkadaşlıklar.
Renkli topluluklara ayrılmış çok sayıda düğüm ve aralarındaki gri kenarlardan oluşan bir sosyal ağ çizimi.

Bir sosyal ağ: kişiler düğüm, ilişkiler kenar

Temel Kavramlar

Derece (Degree)

  • Bir düğümün derecesi, ona bağlı kenar sayısıdır: deg(v).
  • Derecesi 0 olan (yalnız, isolated) düğümler de olabilir.
  • Öz döngü (self-loop) dereceye 2 katkı yapar.
  • Örnek: bir kavşaktaki yolların sayısı.
1 3 3 2 5 2 0 öz döngü yalnız düğüm

Her düğümün içinde kendi derecesi yazıyor

El sıkışma lemmasıHer kenar iki uca birer derece verir: Σ deg(v) = 2mÖrnekte: 1+3+3+2+5+2+0 = 16 = 2·8 kenar.
Yönlü çizgedegiriş derecesi (in-degree): gelen ok sayısı, çıkış derecesi (out-degree): giden ok sayısı.Σ giriş = Σ çıkış = m

Temel Kavramlar

Yönlü Çizge (Digraph)

  • Kenarlar bir düğümden diğerine belirli bir yöndedir: (u, v) ≠ (v, u).
  • Geri dönüş yolu olmayabilir: örnekte B'den A'ya ulaşılamaz.
  • Yönlü çizge (directed graph), kısaca digraph olarak da adlandırılır.
  • Örnek: web sayfaları ve bağlantıları, ders ön koşulları, tek yönlü sokaklar.
A B C E D F
DüğümABCDEF
giriş derecesi021111
çıkış derecesi111120

Temel Kavramlar

Yol (Path) ve Döngü (Cycle)

  • Yol (path): ardışık düğümleri kenarlarla bağlanan düğüm dizisi.
  • Basit yol: hiçbir düğümü tekrar etmeyen yol.
  • Döngü (cycle): aynı düğümde başlayıp biten yol.
  • Basit döngü: başlangıç düğümü dışında hiçbir düğümü tekrar etmez.
  • Çizgelerde döngü olabilir; ağaçta döngü yoktur.
A B C D E F G H I J K L

Yeşil: A-B-C-D-E-F-A · Kırmızı (kesikli): G-H-I-J-K-L-G

Örnek: uçuş rotası. İstanbul → Ankara → İzmir → İstanbul bir döngüdür; aynı şehre uğramadan dönüyorsa basit döngüdür.

Temel Kavramlar

Örnek Çizge

1 2 3 4 5
  • V = {1, 2, 3, 4, 5}
  • E = {(1,2), (1,3), (1,4), (2,5), (3,4), (4,5)}
  • Düğüm 1 ve düğüm 2 komşu.
  • deg(1) = 3, deg(4) = 3, diğerleri 2 → toplam 12 = 2·6 ✓
DiziTürü
1 → 2 → 5basit yol
1 → 3 → 4 → 1basit döngü
1 → 3 → 4 → 1 → 2basit olmayan yol (1 tekrar)
1 → 3 → 4 → 1 → 4 → 1basit olmayan döngü

Temel Kavramlar

Bağlantılı ve Tam Çizge

  • Bağlantılı (connected) çizge: her iki farklı düğüm çifti arasında bir yol vardır.
  • Bağlı bileşen (connected component): birbirine yolla ulaşabilen düğümlerin en büyük grubu.
  • Tam (complete) çizge: her iki farklı düğüm çifti arasında bir kenar vardır.
Bağlantılı: 1 bileşen
Bağlantısız: 3 bileşen
Tam çizge K5: 10 kenar

n düğümlü basit yönsüz çizgede m ≤ n(n−1)/2; bu üst sınıra tam çizgede ulaşılır. Bağlantılı bir çizgede m ≥ n − 1.

Temel Kavramlar

Yönlü Çizge Örneği

1 2 3 4 5
  • V = {1, 2, 3, 4, 5}
  • E = {(1,2), (1,4), (2,5), (4,5), (3,1), (4,3)}
  • Düğüm 2, düğüm 1'in komşusu (1 → 2 kenarı var).
  • Düğüm 1, düğüm 2'nin komşusu değil!
DiziTürü
1 → 2 → 5yönlü yol
1 → 4 → 3 → 1yönlü döngü
5 → …5'ten çıkan kenar yok

Yönlü kenar (u, v) sıralı bir çifttir: u kuyruk (başlangıç), v baş (hedef) düğümdür.

Temel Kavramlar

Ağırlıklı Çizge

  • Her kenara bir sayı (ağırlık, weight) atanır: uzaklık, süre, maliyet, kapasite…
  • Bir yolun uzunluğu = üzerindeki kenar ağırlıklarının toplamı. Yönsüz veya yönlü olabilir.
8 10 3 6 5 7 1 2 3 4 5
Ağırlıklı yönsüz: 3 → 4 → 1 yolu 5 + 3 = 8
8 3 6 7 10 5 1 2 3 4 5
Ağırlıklı yönlü: 1 → 4 → 3 yolu 3 + 5 = 8
Doğrudan kenar her zaman en kısa yol değildir: yönsüz çizgede 1–3 kenarı 10, ama 1 → 4 → 3 yolu yalnızca 8.

Temel Kavramlar

Çizge Soyut Veri Tipi (Graph ADT)

Goodrich'teki Graph arayüzünün temel işlemleri (V: düğüm, E: kenar):

İşlemAçıklama
numVertices(), numEdges()Düğüm sayısı n, kenar sayısı m
vertices(), edges()Tüm düğümler / tüm kenarlar üzerinde gezinme
getEdge(u, v)u'dan v'ye kenar varsa onu, yoksa null döndürür
endVertices(e), opposite(v, e)Kenarın iki ucu / e kenarının v dışındaki ucu
outDegree(v), inDegree(v)Çıkış / giriş derecesi (yönsüzde ikisi eşit)
outgoingEdges(v), incomingEdges(v)v'den çıkan / v'ye gelen kenarlar
insertVertex(x), insertEdge(u, v, x)Yeni düğüm / yeni kenar ekler
removeVertex(v), removeEdge(e)Düğümü (bağlı kenarlarıyla) / kenarı siler

Bu işlemlerin maliyeti, çizgenin bellekte nasıl temsil edildiğine bağlıdır → sonraki bölüm.

Çizge Gösterimleri

Çizge Nasıl Saklanır? Üç Temel Gösterim

Kenar listesiTüm kenarlar tek bir listede tutulur.[(A,B), (A,E), …]
Komşuluk listesiHer düğüm için komşularının listesi tutulur.V[i] = {j, k, l}
Komşuluk matrisin×n iki boyutlu dizi; hücre, kenarın varlığını gösterir.M[i][j] = 1
A B C D E

Kenar listesi (edge list) en basit gösterimdir:

(A, B)(A, E)(B, C)(B, E)(C, D)(D, E)
  • Alan O(n + m); kenar eklemek O(1).
  • Ama "u ile v komşu mu?" ya da "u'nun komşuları kim?" için tüm listeyi taramak gerekir: O(m).

Çizge Gösterimleri

Komşuluk Matrisi (Adjacency Matrix)

  • n×n boyutunda iki boyutlu bir dizidir: matris[i][j] = 1, düğüm i'den j'ye kenar varsa; yoksa 0.
  • Ağırlıklı çizgede matris[i][j] kenarın ağırlığını tutar; kenar yoksa ∞ (veya özel bir değer).
  • Yönsüz çizgede matris simetriktir: matris[i][j] == matris[j][i].
  • Alan karmaşıklığı O(n²); düğüm sayısı arttıkça bellek hızla büyür.

Kolay

  • İki düğüm arasında kenar var mı? O(1)
  • Kenar ekleme / silme O(1)

Zor

  • Bir düğümün komşularını bulmak: tüm satır, O(n)
  • Seyrek çizgede hücrelerin çoğu boş (0)

Çizge Gösterimleri

Komşuluk Matrisi: Üç Örnek

A B C D E
ABCDE
A01001
B10101
C01010
D00101
E11010

Yönsüz çizge: her kenar iki hücreye yazılır, matris köşegene göre simetrik. Satır toplamı = derece (B: 3).

A B C D E
ABCDE
A01001
B00110
C00000
D10101
E01010

Yönlü çizge: satır = kaynak, sütun = hedef. Simetrik değil; satır toplamı çıkış, sütun toplamı giriş derecesi.

4 3 3 2 2 5 2 A B C D E
ABCDE
A04∞∞∞
B∞033∞
C2∞0∞2
D∞∞∞0∞
E∞5∞20

Ağırlıklı çizge: hücrede ağırlık, kenar yoksa ∞ (köşegende 0). Boş hücreye 0 yazmak, 0 ağırlıklı bir kenarla karıştırılabilir.

Çizge Gösterimleri

Komşuluk Listesi (Adjacency List)

  • n düğüm için n adet liste (çoğunlukla bağlı liste veya dinamik dizi) tutulur.
  • liste[i], düğüm i'ye komşu olan düğümleri (ağırlıklıysa ağırlıklarıyla) içerir.
  • Yönsüz çizgede her kenar (v, w) iki listeye de eklenir: w, v'nin listesine; v, w'nin listesine.
  • Alan karmaşıklığı O(n + m); seyrek çizgeler için idealdir.

Kolay

  • Bir düğümün komşularını gezmek: O(deg(v))
  • Kenar ekleme O(1)

Zor

  • u ile v arasında kenar var mı? Listeyi taramak gerekir: O(deg(u))

Çizge Gösterimleri

Komşuluk Listesi: Üç Örnek

A B C D E
A B E B A C E C B D D C E E A B D

Yönsüz: 6 kenar → listelerde 12 kayıt (her kenar iki kez). Liste uzunluğu = derece.

A B C D E
A B E B C D C (boş) D A C E E B D

Yönlü: yalnızca çıkan kenarlar listelenir; 9 kenar → 9 kayıt. C'den çıkan kenar yok, listesi boş.

4 3 3 2 2 5 2 A B C D E
A B 4 B C 3 D 3 C A 2 E 2 D (boş) E B 5 D 2

Ağırlıklı: her kayıt (komşu, ağırlık) çifti tutar; ör. B'nin listesi: (C, 3), (D, 3).

Çizge Gösterimleri

Gösterimlerin Bellek ve İşlem Maliyeti

İşlem (n düğüm, m kenar)Kenar listesiKomşuluk listesiKomşuluk matrisi
BellekO(n + m)O(n + m)O(n²)
u–v kenarı var mı? getEdgeO(m)O(min(deg u, deg v))O(1)
v'nin komşularını gezO(m)O(deg v)O(n)
Seyrek çizge (m ≈ n)Yol ağları, sosyal ağlar → komşuluk listesi. n = 10⁶ düğümde matris 10¹² hücre ister!
Yoğun çizge (m ≈ n²)Sık "kenar var mı?" sorgusu → komşuluk matrisi.

Çizge Gösterimleri

Java ile Komşuluk Listesi

class Cizge {
    private final int n;                                  // düğümler: 0..n-1
    private final List<List<Integer>> komsu = new ArrayList<>();
    Cizge(int n) {
        this.n = n;
        for (int i = 0; i < n; i++) komsu.add(new ArrayList<>());
    }
    void kenarEkle(int u, int v) {
        komsu.get(u).add(v);
        komsu.get(v).add(u);                  // yönlü çizgede bu satır yok
    }
    List<Integer> komsular(int u) { return komsu.get(u); }   // O(1)
    int derece(int u) { return komsu.get(u).size(); }
}
Matris karşılığıboolean[][] m = new boolean[n][n]; kenar ekle: m[u][v] = m[v][u] = true; sorgu m[u][v] O(1).
Ağırlıklı çizgeListe elemanı int[]{v, w} veya küçük bir Kenar sınıfı; matriste int[][], kenar yoksa Integer.MAX_VALUE.

Gezinme (BFS / DFS)

Gezinme Algoritmaları

Gezinme (traversal): bir başlangıç düğümünden ulaşılabilen tüm düğümleri, her birini bir kez sistematik olarak ziyaret etmek.

Genişlik Öncelikli Arama (BFS)Breadth-First Search. Önce tüm yakın komşular, sonra onların komşuları… Seviye seviye ilerler.yardımcı yapı: kuyruk (FIFO)
Derinlik Öncelikli Arama (DFS)Depth-First Search. Bir yol boyunca gidebildiği kadar derine iner, çıkmazda geri döner.yardımcı yapı: yığın (LIFO) / özyineleme
Ağaçtan farkı: çizgede döngü olabilir, aynı düğüme birden çok yoldan gelinebilir → ziyaret edildi işareti (ör. boolean[] ziyaret) şarttır; yoksa algoritma sonsuza kadar döner.

Gezinme (BFS / DFS)

Genişlik Öncelikli Arama (BFS)

  • Düğümleri seviye seviye keşfeder: önce başlangıca 1 kenar uzaklıktakiler, sonra 2 kenar uzaklıktakiler…
  • Kuyruk yapısını kullanır: ilk keşfedilen ilk işlenir.
  • Her düğüm yalnızca bir kez ziyaret edilir.

Artıları

  • Ağırlıksız çizgede en kısa yolu (en az kenar) bulur.
  • Yakın düğümleri hızlı keşfeder.

Eksisi

  • Bellek kullanımı yüksek olabilir: bir seviyenin tamamı kuyrukta bekler.
Örnek: sosyal ağda "arkadaşımın arkadaşları" (2. seviye), bir web tarayıcının (crawler) siteyi katman katman gezmesi.

Gezinme (BFS / DFS)

BFS Algoritması

Sözde kod
BFS(başlangıç):
  kuyruk.ekle(başlangıç)
  başlangıç.ziyaretEdildi()
  while kuyruk boş değil:
    w = kuyruk.çıkar()
    for w'nin ziyaret edilmemiş
        her komşusu u:
      u.ziyaretEdildi()
      kuyruk.ekle(u)

Düğüm kuyruğa girerken işaretlenir; böylece aynı düğüm kuyruğa iki kez girmez.

Java
void bfs(int s) {
  boolean[] ziyaret = new boolean[n];
  Queue<Integer> q = new ArrayDeque<>();
  ziyaret[s] = true;
  q.add(s);
  while (!q.isEmpty()) {
    int w = q.poll();
    System.out.print(w + " ");
    for (int u : komsu.get(w))
      if (!ziyaret[u]) {
        ziyaret[u] = true;
        q.add(u);
      }
  }
}

Gezinme (BFS / DFS)

BFS Adım Adım (başlangıç: A)

I A B C D H G F E Kuyruk (ön → arka) A ön / arka Ziyaret sırası A ziyaret edilmedi kuyrukta işleniyor işlendi

Başlangıç: A ziyaret edildi olarak işaretlenir ve kuyruğa eklenir.

I A B C D H G F E Kuyruk (ön → arka) B F I ön arka Ziyaret sırası A B F I ziyaret edilmedi kuyrukta işleniyor işlendi

A çıkarılır; ziyaret edilmemiş komşuları B, F, I işaretlenip kuyruğa eklenir.

I A B C D H G F E Kuyruk (ön → arka) F I C E ön arka Ziyaret sırası A B F I C E ziyaret edilmedi kuyrukta işleniyor işlendi

B çıkarılır; ziyaret edilmemiş komşuları C, E işaretlenip kuyruğa eklenir.

I A B C D H G F E Kuyruk (ön → arka) I C E G ön arka Ziyaret sırası A B F I C E G ziyaret edilmedi kuyrukta işleniyor işlendi

F çıkarılır; ziyaret edilmemiş komşuları G işaretlenip kuyruğa eklenir.

I A B C D H G F E Kuyruk (ön → arka) C E G ön arka Ziyaret sırası A B F I C E G ziyaret edilmedi kuyrukta işleniyor işlendi

I çıkarılır; ziyaret edilmemiş komşusu yok, kuyruğa bir şey eklenmez.

I A B C D H G F E Kuyruk (ön → arka) E G D ön arka Ziyaret sırası A B F I C E G D ziyaret edilmedi kuyrukta işleniyor işlendi

C çıkarılır; ziyaret edilmemiş komşuları D işaretlenip kuyruğa eklenir.

I A B C D H G F E Kuyruk (ön → arka) G D ön arka Ziyaret sırası A B F I C E G D ziyaret edilmedi kuyrukta işleniyor işlendi

E çıkarılır; ziyaret edilmemiş komşusu yok, kuyruğa bir şey eklenmez.

I A B C D H G F E Kuyruk (ön → arka) D ön / arka Ziyaret sırası A B F I C E G D ziyaret edilmedi kuyrukta işleniyor işlendi

G çıkarılır; ziyaret edilmemiş komşusu yok, kuyruğa bir şey eklenmez.

I A B C D H G F E Kuyruk (ön → arka) H ön / arka Ziyaret sırası A B F I C E G D H ziyaret edilmedi kuyrukta işleniyor işlendi

D çıkarılır; ziyaret edilmemiş komşuları H işaretlenip kuyruğa eklenir.

I A B C D H G F E Kuyruk (ön → arka) (boş) Ziyaret sırası A B F I C E G D H ziyaret edilmedi kuyrukta işleniyor işlendi

H çıkarılır; ziyaret edilmemiş komşusu yok, kuyruğa bir şey eklenmez. Kuyruk boş: gezinme biter. Sıra: A B F I C E G D H

Gezinme (BFS / DFS)

Derinlik Öncelikli Arama (DFS)

  • Düğümleri bir yol boyunca keşfeder: gidebildiği kadar derine iner.
  • Çıkmaza gelince (ziyaret edilmemiş komşu kalmayınca) geri döner (backtracking) ve başka dalı dener.
  • Yığın (stack) yapısı veya özyinelemeli çağrılar kullanılır.
  • Her düğüm yalnızca bir kez ziyaret edilir.

Artıları

  • Bellek kullanımı genellikle düşüktür (yalnızca mevcut yol yığında).
  • Bir yolun sonuna kadar gitme yeteneği sağlar.

Eksisi

  • En kısa yolu garanti etmez.
Kullanım: labirent çözme, döngü tespiti, bağlı bileşenleri bulma, topolojik sıralama.

Gezinme (BFS / DFS)

DFS Algoritması

Özyinelemeli
void dfs(int v, boolean[] ziyaret) {
  ziyaret[v] = true;
  System.out.print(v + " ");
  for (int u : komsu.get(v))
    if (!ziyaret[u])
      dfs(u, ziyaret);
}

Özyineleme, yığını bizim yerimize çağrı yığını (Bölüm 4) ile tutar.

Açık yığınla
void dfsYigin(int s) {
  boolean[] ziyaret = new boolean[n];
  Deque<Integer> yigin = new ArrayDeque<>();
  yigin.push(s);  ziyaret[s] = true;
  while (!yigin.isEmpty()) {
    int v = yigin.peek();
    Integer yeni = null;
    for (int u : komsu.get(v))
      if (!ziyaret[u]) { yeni = u; break; }
    if (yeni == null) yigin.pop(); // geri dön
    else { ziyaret[yeni] = true;
           yigin.push(yeni); }
  }
}

Gezinme (BFS / DFS)

DFS Adım Adım (başlangıç: A)

I A B C D H G F E Yığın A ← üst Ziyaret sırası A ziyaret edilmedi yığında yığının üstü yığından çıktı

Başlangıç: A yığına eklenir ve ziyaret edilir.

I A B C D H G F E Yığın A B ← üst Ziyaret sırası A B ziyaret edilmedi yığında yığının üstü yığından çıktı

A'nin ilk ziyaret edilmemiş komşusu B → yığına eklenir.

I A B C D H G F E Yığın A B C ← üst Ziyaret sırası A B C ziyaret edilmedi yığında yığının üstü yığından çıktı

B'nin ilk ziyaret edilmemiş komşusu C → yığına eklenir.

I A B C D H G F E Yığın A B C D ← üst Ziyaret sırası A B C D ziyaret edilmedi yığında yığının üstü yığından çıktı

C'nin ilk ziyaret edilmemiş komşusu D → yığına eklenir.

I A B C D H G F E Yığın A B C D G ← üst Ziyaret sırası A B C D G ziyaret edilmedi yığında yığının üstü yığından çıktı

D'nin ilk ziyaret edilmemiş komşusu G → yığına eklenir.

I A B C D H G F E Yığın A B C D G E ← üst Ziyaret sırası A B C D G E ziyaret edilmedi yığında yığının üstü yığından çıktı

G'nin ilk ziyaret edilmemiş komşusu E → yığına eklenir.

I A B C D H G F E Yığın A B C D G F ← üst Ziyaret sırası A B C D G E F ziyaret edilmedi yığında yığının üstü yığından çıktı

E: tüm komşuları ziyaret edilmiş → yığından çıkarılır (geri dönüş); G'nin ilk ziyaret edilmemiş komşusu F → yığına eklenir.

I A B C D H G F E Yığın A B C D ← üst Ziyaret sırası A B C D G E F ziyaret edilmedi yığında yığının üstü yığından çıktı

F, G sırayla çıkarılır (geri dönüş).

I A B C D H G F E Yığın A B C D H ← üst Ziyaret sırası A B C D G E F H ziyaret edilmedi yığında yığının üstü yığından çıktı

D'nin ilk ziyaret edilmemiş komşusu H → yığına eklenir.

I A B C D H G F E Yığın A ← üst Ziyaret sırası A B C D G E F H ziyaret edilmedi yığında yığının üstü yığından çıktı

H, D, C, B sırayla çıkarılır (geri dönüş).

I A B C D H G F E Yığın A I ← üst Ziyaret sırası A B C D G E F H I ziyaret edilmedi yığında yığının üstü yığından çıktı

A'nin ilk ziyaret edilmemiş komşusu I → yığına eklenir.

I A B C D H G F E Yığın (boş) Ziyaret sırası A B C D G E F H I ziyaret edilmedi yığında yığının üstü yığından çıktı

I, A sırayla çıkarılır (geri dönüş). Yığın boş: bitti. Sıra: A B C D G E F H I

Gezinme (BFS / DFS)

BFS ve DFS Karşılaştırması

BFSDFS
Yardımcı yapıKuyruk (FIFO)Yığın (LIFO) / özyineleme
Zaman (komşuluk listesi)O(n + m)O(n + m)
Ek bellekO(n): en geniş seviye kuyruktaO(n): en uzun yol yığında
En kısa yol?Evet (ağırlıksız çizgede)Hayır
Tipik kullanımen az adım, seviye bulmadöngü tespiti, bileşenler, labirent
Neden O(n + m)? Her düğüm bir kez işlenir; komşuluk listelerindeki tüm kenarlar bir kez taranır.

Sıralar, komşuların alfabetik sırayla gezildiği varsayımıyla elde edildi; komşu sırası değişirse ziyaret sırası da değişir.

En Kısa Yol

Ağırlıksız En Kısa Yol Problemi

  • Kaynak düğümden diğer tüm düğümlere olan en kısa yolları bulur (tek kaynaklı en kısa yol).
  • Her kenarın aynı ağırlığa (1) sahip olduğu varsayılır: yol uzunluğu = kenar sayısı.
  • Çözüm: BFS. Seviye k'daki düğümün uzaklığı tam olarak k'dır.
1 2 5 3 8 4 6 7 0 1 2 1 2 1 2 3

Kaynak 1; düğümlerin yanındaki sayı 1'e uzaklık

7'ye iki en kısa yol var: 1 → 4 → 6 → 7 ve 1 → 3 → 8 → 7 (ikisi de 3 kenar). BFS bunlardan birini bulur; uzunluk her durumda 3'tür.

En Kısa Yol

Ağırlıksız En Kısa Yol Algoritması

Sözde kod
mesafe[tüm v] = ∞
mesafe[s] = 0
kuyruk.ekle(s)
while kuyruk boş değil:
  w = kuyruk.çıkar()
  for w'nin her komşusu u:
    if mesafe[u] == ∞:
      mesafe[u] = mesafe[w] + 1
      kuyruk.ekle(u)
return mesafe

"mesafe = ∞" aynı zamanda "ziyaret edilmedi" demektir; ayrı bir dizi gerekmez.

Java · O(n + m)
Map<Integer, Integer> agirliksizEnKisaYol(int s) {
  Map<Integer, Integer> mesafe = new HashMap<>();
  for (int v : cizge.keySet())
    mesafe.put(v, Integer.MAX_VALUE);  // ∞
  mesafe.put(s, 0);
  Queue<Integer> kuyruk = new LinkedList<>();
  kuyruk.offer(s);
  while (!kuyruk.isEmpty()) {
    int w = kuyruk.poll();
    for (int u : cizge.get(w))
      if (mesafe.get(u) == Integer.MAX_VALUE) {
        mesafe.put(u, mesafe.get(w) + 1);
        kuyruk.offer(u);
      }
  }
  return mesafe;
}

En Kısa Yol

Ağırlıksız En Kısa Yol Adım Adım

I A B C D H G F E ∞ 0 ∞ ∞ ∞ ∞ ∞ ∞ ∞ Kuyruk (ön → arka) A ön / arka Mesafe tablosu A 0 B ∞ C ∞ D ∞ E ∞ F ∞ G ∞ H ∞ I ∞ ziyaret edilmedi kuyrukta işleniyor işlendi

Başlangıç: mesafe[A] = 0, diğerleri ∞; A kuyruğa eklenir.

I A B C D H G F E 1 0 1 ∞ ∞ ∞ ∞ 1 ∞ Kuyruk (ön → arka) B F I ön arka Mesafe tablosu A 0 B 1 C ∞ D ∞ E ∞ F 1 G ∞ H ∞ I 1 ziyaret edilmedi kuyrukta işleniyor işlendi

A çıkarılır; komşuları B, F, I'nın mesafesi ∞ → 0 + 1 = 1, kuyruğa eklenir.

I A B C D H G F E 1 0 1 2 ∞ ∞ ∞ 1 2 Kuyruk (ön → arka) F I C E ön arka Mesafe tablosu A 0 B 1 C 2 D ∞ E 2 F 1 G ∞ H ∞ I 1 ziyaret edilmedi kuyrukta işleniyor işlendi

B çıkarılır; A zaten 0, C ve E ∞ → 1 + 1 = 2.

I A B C D H G F E 1 0 1 2 ∞ ∞ 2 1 2 Kuyruk (ön → arka) I C E G ön arka Mesafe tablosu A 0 B 1 C 2 D ∞ E 2 F 1 G 2 H ∞ I 1 ziyaret edilmedi kuyrukta işleniyor işlendi

F çıkarılır; G ∞ → 2 (A'nın mesafesi değişmez).

I A B C D H G F E 1 0 1 2 3 ∞ 2 1 2 Kuyruk (ön → arka) E G D ön arka Mesafe tablosu A 0 B 1 C 2 D 3 E 2 F 1 G 2 H ∞ I 1 ziyaret edilmedi kuyrukta işleniyor işlendi

I çıkarılır (yeni komşu yok); C çıkarılır, D ∞ → 2 + 1 = 3.

I A B C D H G F E 1 0 1 2 3 ∞ 2 1 2 Kuyruk (ön → arka) D ön / arka Mesafe tablosu A 0 B 1 C 2 D 3 E 2 F 1 G 2 H ∞ I 1 ziyaret edilmedi kuyrukta işleniyor işlendi

E ve G çıkarılır; tüm komşularının mesafesi zaten belli, değişiklik yok.

I A B C D H G F E 1 0 1 2 3 4 2 1 2 Kuyruk (ön → arka) H ön / arka Mesafe tablosu A 0 B 1 C 2 D 3 E 2 F 1 G 2 H 4 I 1 ziyaret edilmedi kuyrukta işleniyor işlendi

D çıkarılır; H ∞ → 3 + 1 = 4.

I A B C D H G F E 1 0 1 2 3 4 2 1 2 Kuyruk (ön → arka) (boş) Mesafe tablosu A 0 B 1 C 2 D 3 E 2 F 1 G 2 H 4 I 1 ziyaret edilmedi kuyrukta işleniyor işlendi

H çıkarılır; kuyruk boş. Sonuç: A 0 · B, F, I 1 · C, E, G 2 · D 3 · H 4.

En Kısa Yol

Ağırlıklı En Kısa Yol Problemi

  • Kaynak düğümden diğer tüm düğümlere olan en kısa yolları bulur.
  • Her kenarın farklı bir ağırlığı olabilir: uzaklık, süre, maliyet…
  • Yol uzunluğu = kenar ağırlıklarının toplamı.
4 2 5 10 3 4 11 A B D C E F

A'dan F'ye en kısa yol: A → C → E → D → F = 2 + 3 + 4 + 11 = 20

BFS burada yetmezEn az kenarlı yol A → B → D → F (3 kenar) ama uzunluğu 4 + 10 + 11 = 25.
Çözüm: Dijkstra algoritmasıEdsger W. Dijkstra, 1956. Ağırlıklar negatif olmamalıdır.

En Kısa Yol

Dijkstra Algoritması: Fikir ve Sözde Kod

  • Kesinleşmemiş düğümlerden mesafesi en küçük olanı seç.
  • Komşuların mesafesini gevşetme ile güncelle.
  • Seçim için öncelikli kuyruk, yolu kurmak için önceki[] kullan.
Dijkstra(G, s):
  for her düğüm v:
    mesafe[v] = ∞
    önceki[v] = tanımsız
  mesafe[s] = 0
  Q = tüm düğümler  // öncelikli kuyruk
  while Q boş değil:
    u = Q.çıkar()   // en küçük mesafe[u]
    for u'nun Q'daki her komşusu v:
      alt = mesafe[u] + ağırlık(u, v)
      if alt < mesafe[v]:
        mesafe[v] = alt
        önceki[v] = u
        // Q'da v'nin önceliğini azalt

En Kısa Yol

Dijkstra Algoritması: Java

int[] dijkstra(List<List<int[]>> adj, int s) {   // adj.get(u): {komşu, ağırlık} dizileri
    int[] d = new int[adj.size()];
    Arrays.fill(d, Integer.MAX_VALUE);  d[s] = 0;
    PriorityQueue<int[]> pq =                       // {düğüm, mesafe}, mesafeye göre
        new PriorityQueue<>((a, b) -> Integer.compare(a[1], b[1]));
    pq.add(new int[]{s, 0});
    while (!pq.isEmpty()) {
        int[] e = pq.poll();  int u = e[0];
        if (e[1] > d[u]) continue;                   // bayat kayıt: atla
        for (int[] k : adj.get(u)) {
            int v = k[0], alt = d[u] + k[1];
            if (alt < d[v]) { d[v] = alt; pq.add(new int[]{v, alt}); }
        }
    }
    return d;
}
Öncelik = mesafe (düğüm numarası değil). Java'nın PriorityQueue'sunda "önceliği azalt" yok: yeni kayıt eklenir, eskisi çıkınca bayat olarak atlanır. Yol için güncellemeye onceki[v] = u; eklenir.

En Kısa Yol

Dijkstra Adım Adım (kaynak: A)

3 4 7 1 2 3 7 2 2 3 5 I A B C D H G F E düğüm A B C D E F G H I mesafe 0 ∞ ∞ ∞ ∞ ∞ ∞ ∞ ∞ önceki – – – – – – – – – Öncelik kuyruğu (küçük mesafe önde) A, 0 Kesinleşenler: – ∞ (henüz ulaşılmadı) geçici mesafe yeni kesinleşen kesinleşmiş

Başlangıç: mesafe[A] = 0, diğerleri ∞. Öncelik kuyruğunda yalnızca (A, 0) var.

3 4 7 1 2 3 7 2 2 3 5 I A B C D H G F E düğüm A B C D E F G H I mesafe 0 4 ∞ ∞ ∞ 7 ∞ ∞ 3 önceki – A – – – A – – A Öncelik kuyruğu (küçük mesafe önde) I, 3 B, 4 F, 7 Kesinleşenler: A ∞ (henüz ulaşılmadı) geçici mesafe yeni kesinleşen kesinleşmiş

En küçük mesafeli A (0) çıkarılır ve kesinleşir. B: ∞ → 4; F: ∞ → 7; I: ∞ → 3.

3 4 7 1 2 3 7 2 2 3 5 I A B C D H G F E düğüm A B C D E F G H I mesafe 0 4 ∞ ∞ ∞ 7 ∞ ∞ 3 önceki – A – – – A – – A Öncelik kuyruğu (küçük mesafe önde) B, 4 F, 7 Kesinleşenler: A, I ∞ (henüz ulaşılmadı) geçici mesafe yeni kesinleşen kesinleşmiş

En küçük mesafeli I (3) çıkarılır ve kesinleşir. Kesinleşmemiş komşusu yok.

3 4 7 1 2 3 7 2 2 3 5 I A B C D H G F E düğüm A B C D E F G H I mesafe 0 4 5 ∞ 6 7 ∞ ∞ 3 önceki – A B – B A – – A Öncelik kuyruğu (küçük mesafe önde) C, 5 E, 6 F, 7 Kesinleşenler: A, I, B ∞ (henüz ulaşılmadı) geçici mesafe yeni kesinleşen kesinleşmiş

En küçük mesafeli B (4) çıkarılır ve kesinleşir. C: ∞ → 5; E: ∞ → 6.

3 4 7 1 2 3 7 2 2 3 5 I A B C D H G F E düğüm A B C D E F G H I mesafe 0 4 5 12 6 7 ∞ ∞ 3 önceki – A B C B A – – A Öncelik kuyruğu (küçük mesafe önde) E, 6 F, 7 D, 12 Kesinleşenler: A, I, B, C ∞ (henüz ulaşılmadı) geçici mesafe yeni kesinleşen kesinleşmiş

En küçük mesafeli C (5) çıkarılır ve kesinleşir. D: ∞ → 12; E: 5 + 3 = 8 ≥ 6, değişmez.

3 4 7 1 2 3 7 2 2 3 5 I A B C D H G F E düğüm A B C D E F G H I mesafe 0 4 5 12 6 7 8 ∞ 3 önceki – A B C B A E – A Öncelik kuyruğu (küçük mesafe önde) F, 7 G, 8 D, 12 Kesinleşenler: A, I, B, C, E ∞ (henüz ulaşılmadı) geçici mesafe yeni kesinleşen kesinleşmiş

En küçük mesafeli E (6) çıkarılır ve kesinleşir. G: ∞ → 8.

3 4 7 1 2 3 7 2 2 3 5 I A B C D H G F E düğüm A B C D E F G H I mesafe 0 4 5 12 6 7 8 ∞ 3 önceki – A B C B A E – A Öncelik kuyruğu (küçük mesafe önde) G, 8 D, 12 Kesinleşenler: A, I, B, C, E, F ∞ (henüz ulaşılmadı) geçici mesafe yeni kesinleşen kesinleşmiş

En küçük mesafeli F (7) çıkarılır ve kesinleşir. G: 7 + 2 = 9 ≥ 8, değişmez.

3 4 7 1 2 3 7 2 2 3 5 I A B C D H G F E düğüm A B C D E F G H I mesafe 0 4 5 11 6 7 8 ∞ 3 önceki – A B G B A E – A Öncelik kuyruğu (küçük mesafe önde) D, 11 Kesinleşenler: A, I, B, C, E, F, G ∞ (henüz ulaşılmadı) geçici mesafe yeni kesinleşen kesinleşmiş

En küçük mesafeli G (8) çıkarılır ve kesinleşir. D: 12 → 11.

3 4 7 1 2 3 7 2 2 3 5 I A B C D H G F E düğüm A B C D E F G H I mesafe 0 4 5 11 6 7 8 16 3 önceki – A B G B A E D A Öncelik kuyruğu (küçük mesafe önde) H, 16 Kesinleşenler: A, I, B, C, E, F, G, D ∞ (henüz ulaşılmadı) geçici mesafe yeni kesinleşen kesinleşmiş

En küçük mesafeli D (11) çıkarılır ve kesinleşir. H: ∞ → 16.

3 4 7 1 2 3 7 2 2 3 5 I A B C D H G F E düğüm A B C D E F G H I mesafe 0 4 5 11 6 7 8 16 3 önceki – A B G B A E D A Öncelik kuyruğu (küçük mesafe önde) (boş) Kesinleşenler: A, I, B, C, E, F, G, D, H ∞ (henüz ulaşılmadı) geçici mesafe yeni kesinleşen kesinleşmiş

En küçük mesafeli H (16) çıkarılır ve kesinleşir. Kesinleşmemiş komşusu yok.

3 4 7 1 2 3 7 2 2 3 5 I A B C D H G F E düğüm A B C D E F G H I mesafe 0 4 5 11 6 7 8 16 3 önceki – A B G B A E D A Öncelik kuyruğu (küçük mesafe önde) (boş) Kesinleşenler: A, I, B, C, E, F, G, D, H ∞ (henüz ulaşılmadı) geçici mesafe yeni kesinleşen kesinleşmiş

Yolu bulmak için önceki zinciri geri izlenir: H ← D ← G ← E ← B ← A. Yol: A → B → E → G → D → H = 4 + 2 + 2 + 3 + 5 = 16.

En Kısa Yol

Dijkstra Algoritmasının Analizi

UygulamaKarmaşıklıkNeden?
Öncelikli kuyruk (ikili heap)O((n + m) log n)n kez en küçüğü çıkar, en çok m kez güncelle/ekle; her biri O(log n)
Kuyruksuz (dizi taraması)O(n² + m) = O(n²)Her adımda en küçük mesafeli düğümü bulmak için n düğüm taranır; komşu kontrolleri toplam m
Hangisi ne zaman?Seyrek çizgede (m ≈ n) heap: O(n log n). Çok yoğun çizgede (m ≈ n²) dizi taraması O(n²) daha iyi olabilir.
Negatif ağırlıkKesinleşen bir mesafe sonradan negatif kenarla kısalabilir → Dijkstra yanlış sonuç verir. Bu durumda Bellman-Ford kullanılır.
Neden doğru? Ağırlıklar ≥ 0 iken, kuyruktaki en küçük mesafeli düğüme başka bir düğüm üzerinden daha kısa ulaşılamaz: öbür yollar zaten en az bu kadar uzundur.

Özet

Özet

KavramlarDüğüm, kenar, derece, yön, ağırlık, yol, döngü ve bağlı bileşen.
GösterimlerSeyrek çizgede komşuluk listesi; hızlı kenar sorgusunda matris.
AlgoritmaYapıZaman (liste ile)Ne verir?
BFSkuyrukO(n + m)seviye sırası, ağırlıksız en kısa yol
DFSyığın / özyinelemeO(n + m)derinlemesine gezinme, döngü, bileşenler
Dijkstraöncelikli kuyrukO((n + m) log n)ağırlıklı en kısa yol (ağırlık ≥ 0)
BFS kuyruk, DFS yığın, Dijkstra öncelikli kuyruk kullanır.

Özet

Etkileşimli Simülatörler

Bu bölümün konularını tarayıcıda deneyerek pekiştirin:

Yönsüz ÇizgeDüğüm/kenar ekle-sil, BFS ve DFS, bağlı bileşenler, komşuluk listesi ve matrisi görünümü.
Yönlü ÇizgeOklu kenarlar, giriş/çıkış dereceleri ve yönlü gezinme.
DijkstraAğırlıklı çizgede en kısa yolları adım adım izleyin.

Özet

Örnek Problemler

  1. 10 düğümlü basit yönsüz bir çizgede en fazla kaç kenar olabilir? Derecelerin toplamı 30 ise kaç kenar vardır?
  2. n = 10.000 düğüm, m = 30.000 kenar olan bir yol ağını hangi gösterimle saklarsınız? Neden?
  3. Gezinme örneğindeki çizgede BFS ve DFS'yi H'den başlatın (komşular alfabetik).
  4. DFS'yi yığın yerine kuyrukla yazarsak hangi algoritmayı elde ederiz?
  5. Ağırlıklı en kısa yol örneğinde B → C kenarı 5 yerine 1 olsaydı A'dan D'ye en kısa yol ne olurdu?
Cevapları göster
  1. 10·9/2 = 45 kenar; Σ deg = 2m → m = 15.
  2. Komşuluk listesi: O(n + m) ≈ 40 bin kayıt; matris 10⁸ hücre ister ve çoğu 0 olur.
  3. BFS: H D C G B E F A I · DFS: H D C B A F G E I.
  4. Ziyaret sırası BFS'ye dönüşür (ön kısım kuyruk mantığıyla işlenir).
  5. A → C yolu değişmez (2 < 4 + 1); D için A → C → E → D = 2 + 3 + 4 = 9, yine 9.

Özet

Kaynaklar

  • Goodrich, Tamassia ve Goldwasser, Data Structures and Algorithms in Java, 6. baskı, 2014.
  • Cormen, Leiserson, Rivest ve Stein, Introduction to Algorithms, 4. baskı, 2022.
  • Sedgewick ve Wayne, Algorithms, 4. baskı, 2011.

Son

Bölüm 11: Çizgeler
Sonraki bölüm: Kümeler
1 / 1 Sercan KÜLCÜ, Tüm hakları saklıdır.

← → veya boşluk ile gezinin · F: tam ekran · Home/End: ilk/son slayt