Bölüm 14: Çizgeler

Bölüm 14: Çizgeler · Çalışma Soruları
Temel kavramlarÇizge gösterimleriBFS ve DFSBileşenler ve topolojik sıralamaAğırlıksız en kısa yolDijkstraKruskal ve Prim
Sercan KÜLCÜ

Klasik Soru · Temel Kavramlar

Soru 1: Derece ve El Sıkışma Lemması

V = {0, 1, 2, 3, 4}, E = {(0,1), (0,4), (1,2), (1,3), (1,4), (2,3), (3,4)} yönsüz çizgesinde her düğümün derecesini bulun ve el sıkışma lemmasını (Σ deg(v) = 2m) doğrulayın.

Cevabı göster
v01234
deg(v)24233

Σ deg = 2 + 4 + 2 + 3 + 3 = 14 = 2 · 7 (m = 7). Her kenar iki ucuna birer derece verdiği için toplam her zaman kenar sayısının iki katıdır.

Sonuç: tek dereceli düğüm sayısı (burada 3 ve 4) her zaman çifttir.

Çoktan Seçmeli · Temel Kavramlar

Soru 2: Derece Dizisi Mümkün mü?

Basit yönsüz bir çizgenin düğüm dereceleri 3, 3, 2, 2, 1 olabilir mi?

Doğru C: toplam 11 tek sayı; el sıkışma lemmasına göre toplam 2m olmalı, yani 11 / 2 = 5,5 kenar gerekirdi. A çekici ama böyle bir çizge yoktur; B'deki koşul gerekli ama yeterli değildir.

Çoktan Seçmeli · Temel Kavramlar

Soru 3: Yol Türleri

V = {1, …, 5}, E = {(1,2), (1,3), (1,4), (2,5), (3,4), (4,5)} yönsüz çizgesinde hangisi basit olmayan bir yoldur?

Doğru A: tüm kenarlar (1–4, 4–3, 3–1, 1–2) var ama 1 iki kez geçiyor → yol, fakat basit değil. C çekici ama bir basit döngüdür (yalnızca başlangıç tekrar eder). B basit yoldur; D'de 5–3 kenarı olmadığı için yol değildir.

Çoktan Seçmeli · Temel Kavramlar

Soru 4: Yönlü Kenar ve Komşuluk

Yönlü bir çizgede (u, v) kenarı var, (v, u) kenarı yok. Hangisi kesinlikle doğrudur?

Doğru B: u kuyruk (başlangıç), v baştır (hedef); komşuluk yönlüdür. C çekici ama yanlış: v'den u'ya başka düğümler üzerinden (v → w → u) bir yol olabilir. D: bu kenar u'nun çıkış derecesini artırır.

Klasik Soru · Çizge Gösterimleri

Soru 5: Yönlü Çizgenin Komşuluk Matrisi

Kenarları A→B, A→D, B→C, C→A, D→C, D→E, E→B olan yönlü çizgenin komşuluk matrisini yazın; A'nın çıkış derecesi ve C'nin giriş derecesi matristen nasıl okunur?

Cevabı göster
ABCDE
A01010
B00100
C10000
D00101
E01000

Satır = kaynak, sütun = hedef. A'nın çıkış derecesi = A satırının toplamı = 2; C'nin giriş derecesi = C sütununun toplamı = 2 (B→C, D→C).

Matris simetrik değildir (ör. A→B var, B→A yok). Bellek O(n²) = 25 hücre, yalnızca 7'si 1.

Çoktan Seçmeli · Çizge Gösterimleri

Soru 6: Ağırlıklı Matriste Boş Hücre

Ağırlıklı bir çizgenin komşuluk matrisinde kenar olmayan hücrelere neden 0 yerine ∞ (ör. Integer.MAX_VALUE) yazılır?

Doğru D: kenarsız hücrede 0, sahte ve bedava bir kenar demektir (köşegendeki 0 ise kendine uzaklık olarak anlamlıdır). B tam tersi: Java int[][]'i zaten 0 ile başlatır; bu yüzden ∞ açıkça doldurulmalıdır.

Klasik Soru · Çizge Gösterimleri

Soru 7: kenarEkle Sonrası Komşuluk Listeleri

Sunumdaki Cizge sınıfıyla (yönsüz kenarEkle) aşağıdaki kod çalıştıktan sonra beş komşu listesinin içeriğini ekleme sırasıyla yazın.

Cizge g = new Cizge(5);
int[][] E = {{2,0}, {0,3}, {3,1},
             {1,4}, {2,3}, {4,3}};
for (int[] e : E)
    g.kenarEkle(e[0], e[1]);
// kenarEkle(u, v):
//   komsu.get(u).add(v);
//   komsu.get(v).add(u);
Cevabı göster

0: [2, 3] · 1: [3, 4] · 2: [0, 3]
3: [0, 1, 2, 4] · 4: [1, 3]

Her kenar iki listeye eklenir → 6 kenar, 12 kayıt (= 2m). Liste uzunluğu dereceyi verir: derece(3) = 4.

Listeler sıralı değildir; sıra ekleme sırasıdır. BFS/DFS'nin ziyaret sırası da bu sıraya bağlıdır. Her kenarEkle O(1), bellek O(n + m).

Çoktan Seçmeli · Çizge Gösterimleri

Soru 8: getEdge Maliyeti

Graph ADT'deki getEdge(u, v) ("u–v kenarı var mı?") işleminin yönsüz çizgede kenar listesi, komşuluk listesi, komşuluk matrisi gösterimlerindeki maliyeti sırasıyla nedir?

Doğru A: kenar listesi tüm kenarları tarar; komşuluk listesinde kısa olan liste taranır; matriste tek hücre m[u][v] okunur. C çekici ama matris sorgusu satırı taramaz; O(n) satır taraması "komşuları gez" işleminin maliyetidir.

Klasik Soru · Çizge Gösterimleri

Soru 9: Gösterim Seçimi: Yol Ağı

n = 10⁵ kavşak ve m = 3 · 10⁵ çift yönlü yoldan oluşan bir yol ağını komşuluk matrisiyle mi, komşuluk listesiyle mi saklarsınız? Bellek gereksinimini sayılarla karşılaştırarak gerekçelendirin.

Cevabı göster

Komşuluk listesi.

  • Matris: n² = 10¹⁰ hücre (hücre başına 1 bayt bile ≈ 10 GB); dolu hücre yalnızca 2m = 6 · 10⁵ → %0,006.
  • Liste: n liste + 2m = 6 · 10⁵ kayıt → O(n + m) ≈ 7 · 10⁵ öğe, birkaç MB.

Çizge seyrektir (m ≈ 3n). Gezinme de listede O(n + m), matriste O(n²) sürer. Matris; yoğun çizgede (m ≈ n²) ve sık "kenar var mı?" sorgusunda tercih edilir.

Klasik Soru · Gezinme (BFS / DFS)

Soru 10: Hatalı BFS: İşaret Nerede?

Bu BFS'de düğüm kuyruğa eklenirken değil, çıkarılırken işaretleniyor. Kenarları 0–1, 0–2, 1–2 olan üçgende (komşular küçükten büyüğe) bfs(0) ne yazdırır?

void bfs(int s) {
  boolean[] ziyaret = new boolean[n];
  Queue<Integer> q = new ArrayDeque<>();
  q.add(s);
  while (!q.isEmpty()) {
    int w = q.poll();
    ziyaret[w] = true;   // işaret burada
    System.out.print(w + " ");
    for (int u : komsu.get(w))
      if (!ziyaret[u]) q.add(u);
  }
}
Cevabı göster

Çıktı: 0 1 2 2

  • 0 çıkar → 1 ve 2 eklenir: q = [1, 2].
  • 1 çıkar → 2 henüz işaretsiz, tekrar eklenir: q = [2, 2].
  • 2 iki kez çıkar ve iki kez yazdırılır.

Düzeltme: düğüm kuyruğa girerken işaretlenmeli (ziyaret[u] = true; q.add(u);, başta ziyaret[s] = true). Böylece her düğüm kuyruğa bir kez girer; aksi hâlde kuyruk O(m) büyür.

Adım Adım Çalıştırma · Gezinme (BFS / DFS)

Soru 11: BFS Sırası

Komşu listeleri 0: [2, 4] · 1: [3, 5] · 2: [0, 3] · 3: [1, 2, 5] · 4: [0, 5] · 5: [1, 3, 4]. bfs(0) hangi sırayı yazdırır?

012345
012345

0 kuyruğa girerken işaretlenir.

012345

0 kuyruktan çıkar ve yazdırılır; komşuları 2, 4.

012345

2 ve 4 işaretlenip kuyruğa eklenir (seviye 1).

012345

2 çıkar; komşuları 0, 3.

012345

0 zaten işaretli → atlanır; 3 eklenir (seviye 2).

012345

4 çıkar; komşuları 0, 5.

012345

0 atlanır; 5 eklenir (seviye 2).

012345

3 çıkar; komşuları 1, 2, 5.

012345

1 eklenir (seviye 3); 2 ve 5 zaten işaretli.

012345

5 çıkar; komşuları 1, 3, 4 hepsi işaretli → ekleme yok.

012345

1 çıkar; komşuları 3, 5 işaretli.

012345

Kuyruk boş → biter. Seviyeler: {0}, {2, 4}, {3, 5}, {1}. O(n + m).

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);
      }
  }
}

Çoktan Seçmeli · Gezinme (BFS / DFS)

Soru 12: Özyinelemeli DFS Sırası

Komşu listeleri alfabetik olan bu çizgede özyinelemeli dfs(H) hangi sırayı yazdırır?

A: B F I    B: A C E    C: B D E
D: C G H    E: B C G    F: A G
G: D E F    H: D        I: A

Doğru C: H → D → C → B → A (her adımda alfabetik ilk ziyaret edilmemiş komşu) → F → G → E; çıkmazda geri dönülür ve A'dan I'ya gidilir. A çekici ama o BFS sırasıdır (seviye seviye). D'de B'den önce A yerine E seçilmiş.

Klasik Soru · Gezinme (BFS / DFS)

Soru 13: Bağlantılı Bileşenler

n = 8 ve kenarlar (0,4), (4,6), (1,2), (5,7), (7,3) iken bilesenler(bil) çağrısından sonra bil[] dizisi ve dönüş değeri nedir?

int bilesenler(int[] bil) {
  Arrays.fill(bil, -1);
  int say = 0;
  for (int s = 0; s < n; s++)
    if (bil[s] == -1) dfs(s, say++, bil);
  return say;
}
void dfs(int v, int c, int[] bil) {
  bil[v] = c;
  for (int u : komsu.get(v))
    if (bil[u] == -1) dfs(u, c, bil);
}
Cevabı göster

bil = [0, 1, 1, 2, 0, 2, 0, 2], dönüş 3.

  • s = 0: dfs {0, 4, 6} → bileşen 0.
  • s = 1: dfs {1, 2} → bileşen 1.
  • s = 2: zaten boyalı. s = 3: dfs {3, 7, 5} → bileşen 2 (3, 5'ten önce gelir).

Artık "u ile v aynı bileşende mi?" sorusu bil[u] == bil[v] ile O(1). Toplam O(n + m).

Çoktan Seçmeli · Gezinme (BFS / DFS)

Soru 14: İki Parçalı Çizge

Aşağıdaki çizgelerden hangisi iki parçalıdır (BFS ile 2-renklenebilir)?

Doğru C: iki parçalı ⇔ tek uzunlukta döngü yok. C6'da renkler 0, 1, 0, 1, 0, 1 diye gider; kapanış kenarı da zıt renkleri bağlar. B çekici ama C5 tek uzunluklu: BFS aynı renkli iki komşu bulur → false. K4 üçgen içerir.

Adım Adım Çalıştırma · Gezinme (BFS / DFS)

Soru 15: Kahn ile Topolojik Sıralama

adj: 0: [] · 1: [] · 2: [3] · 3: [1] · 4: [0, 1] · 5: [2, 0] olan DAG için kahn(adj) hangi sırayı döndürür?

Giriş dereceleri sayılır: 0 ← 4, 5 · 1 ← 3, 4 · 2 ← 5 · 3 ← 2.

Giriş derecesi 0 olan 4 ve 5 kuyruğa girer: hiçbir şeye bağımlı değiller.

4 çıkar ve sonuca eklenir.

4→0 ve 4→1 silinmiş sayılır; 0 ve 1 hâlâ birer ön koşul bekliyor.

5 çıkar ve sonuca eklenir.

5→2: giris[2] = 0 → 2 kuyruğa; 5→0: giris[0] = 0 → 0 kuyruğa.

2 çıkar ve sonuca eklenir.

2→3: giris[3] = 0 → 3 kuyruğa.

0 çıkar; listesi boş, kimse güncellenmez.

3 çıkar ve sonuca eklenir.

3→1: giris[1] = 0 → 1 kuyruğa.

1 çıkar ve sonuca eklenir.

Kuyruk boş. Boyut 6 = n → döngü yok. Sıra: 4 5 2 0 3 1. O(n + m).

List<Integer> kahn(List<List<Integer>> adj) {
  int n = adj.size();
  int[] giris = new int[n];
  for (List<Integer> l : adj)
    for (int v : l) giris[v]++;
  Queue<Integer> q = new ArrayDeque<>();
  for (int v = 0; v < n; v++)
    if (giris[v] == 0) q.add(v);
  List<Integer> sonuc = new ArrayList<>();
  while (!q.isEmpty()) {
    int u = q.poll();
    sonuc.add(u);
    for (int v : adj.get(u))
      if (--giris[v] == 0) q.add(v);
  }
  return sonuc;  // boyut < n → döngü
}

Klasik Soru · Gezinme (BFS / DFS)

Soru 16: Hatalı Döngü Tespiti

renk[v] = 2 satırı unutulmuştur. Kenarları 0→1, 0→2, 1→2 olan DAG için donguVar(0, renk) ne döndürür ve neden?

// renk: 0 beyaz, 1 gri, 2 siyah
boolean donguVar(int v, int[] renk) {
  renk[v] = 1;
  for (int u : komsu.get(v)) {
    if (renk[u] == 1) return true;
    if (renk[u] == 0 && donguVar(u, renk))
      return true;
  }
  // renk[v] = 2;  (unutulmuş)
  return false;
}
Cevabı göster

true döner: döngü olmadığı hâlde yanlış alarm.

  • 0 gri → 1 gri → 2 gri; 2'nin çıkan kenarı yok, false döner ama 2 gri kalır. 1 de gri kalır.
  • 0'a dönülür; 0→2 kenarında renk[2] == 1 → geri kenar sanılır.

Doğrusu: işi biten düğüm siyah (2) olmalı. Yalnızca gri (şu anki yolda) düğüme giden kenar döngü demektir; siyaha giden kenar döngü değildir. Düzeltilmiş kod false döndürür.

Çoktan Seçmeli · En Kısa Yol

Soru 17: Ağırlıklı Çizgede BFS

Bu ağırlıklı yönlü çizgede BFS'nin A'dan F'ye bulduğu yolun ağırlıklı uzunluğu nedir (komşular alfabetik)?

A→B 4   A→C 2   B→C 5
B→D 10  C→E 3   E→D 4
D→F 11

Doğru B: BFS en az kenarlı yolu bulur: A→B→D→F (3 kenar) = 4 + 10 + 11 = 25. A çekici ama 20, gerçek en kısa yol A→C→E→D→F'nin uzunluğudur (Dijkstra'nın sonucu). C kenar sayısıdır, ağırlık değil.

Klasik Soru · En Kısa Yol

Soru 18: Dijkstra'yı Elle Uygulama

Ağırlıklı yönsüz çizgede A'dan başlayarak Dijkstra ile her düğümün en kısa mesafesini ve onceki[] değerini bulun; düğümler hangi sırayla kesinleşir?

421581026317ABCDEFG
Cevabı göster
ABCDEFG
d0328101314
önceki–CABDEF

Kesinleşme sırası: A C B D E F G

  • C = 2 kesinleşince B, 4'ten 2 + 1 = 3'e iner.
  • D = 3 + 5 = 8 (A–C–D = 10'dan iyi); E = 8 + 2 = 10 (C–E ile 12).
  • F = 10 + 3 = 13 (D–F ile 14); G = 13 + 1 = 14 (E–G ile 17).

Çoktan Seçmeli · En Kısa Yol

Soru 19: Bayat Kayıt Kontrolü

Java Dijkstra'da işaretli continue satırı silinirse (ağırlıklar ≥ 0) ne olur?

long[] e = pq.poll();
int u = (int) e[0];
if (e[1] > d[u]) continue; // bayat
for (int[] k : adj.get(u)) {
  int v = k[0];
  long alt = d[u] + k[1];
  if (alt < d[v]) { d[v] = alt;
    pq.add(new long[]{v, alt}); }
}

Doğru D: bayat kayıt çıktığında d[u] zaten daha küçüktür ve komşular bu d[u] ile önceden gevşetilmiştir; alt < d[v] bir daha sağlanmaz. A çekici ama satır doğruluk için değil verim içindir (Java PQ'da "önceliği azalt" olmadığından eklenen kopyalar).

Klasik Soru · Minimum Kapsayan Ağaç

Soru 20: Kruskal ile MKA

Çizgenin minimum kapsayan ağacını (MKA) Kruskal algoritmasıyla bulunuz: kenarları seçilme sırasıyla ve toplam ağırlığı yazınız; algoritma hangi kenardan sonra durur?

635274891ABCDEF
Cevabı göster
Kenarwfind(u) ≠ find(v)?Karar
E–F1evetkabul
B–D2evetkabul
A–C3evetkabul
C–E4evetkabul
B–C5evetkabul → |T| = 5 = n − 1

Toplam ağırlık 1 + 2 + 3 + 4 + 5 = 15. B–C'den sonra |T| = n − 1 olduğu için algoritma durur; A–B (6), C–D (7), D–E (8), D–F (9) hiç incelenmez. İncelenseydi A–B reddedilirdi: A ile B zaten A–C–B yoluyla aynı kümede (döngü).

Union-Find, "bu kenar döngü kurar mı?" sorusunu find(u) == find(v) karşılaştırmasıyla neredeyse sabit sürede yanıtlar.

Çoktan Seçmeli · Minimum Kapsayan Ağaç

Soru 21: Kruskal'ın Maliyeti

n düğümlü, m kenarlı bir çizgede Union-Find ile uygulanan Kruskal algoritmasının toplam süresini hangi aşama belirler?

Doğru: D. 2m find + (n − 1) union yalnızca O(m · α(n)), yani neredeyse doğrusal; baskın terim sıralamadır. m ≤ n² olduğundan log m ≤ 2 log n, dolayısıyla O(m log m) = O(m log n). B çekicidir, ama döngü kontrolü Union-Find yerine DFS ile yapılsaydı geçerli olurdu.

Klasik Soru · Minimum Kapsayan Ağaç

Soru 22: Prim ile MKA

Soru 20'deki çizgede Prim algoritmasını A'dan başlatınız. Ağaca giren kenarları sırasıyla ve toplam ağırlığı yazınız. Sonuç Kruskal'ınkiyle karşılaştırıldığında ne görülür?

635274891ABCDEF
Cevabı göster
AdımAğaçEn hafif dış kenar
1AA–C 3
2A, CC–E 4
3A, C, EE–F 1
4A, C, E, FC–B 5
5A, B, C, E, FB–D 2

Toplam 3 + 4 + 1 + 5 + 2 = 15: Kruskal'la aynı kenarlar, farklı sırada. Prim E–F (1) kenarını ancak E ağaca girince görebilir; Kruskal onu ilk seçer.

Çoktan Seçmeli · Minimum Kapsayan Ağaç

Soru 23: Prim'in Seçimi

Prim algoritması her adımda hangi kenarı ağaca ekler?

Doğru: C. Kenarın bir ucu ağaçta, öbür ucu dışarıda olmalıdır; bu kenarların en hafifi seçilir. A Kruskal'ın kuralıdır (döngü kontrolüyle). B Dijkstra'nın anahtarıdır. D yanlıştır: en hafif dış kenar daha önce eklenmiş bir düğümden çıkabilir.

Çoktan Seçmeli · Minimum Kapsayan Ağaç

Soru 24: Bayat Kayıt

Öncelikli kuyrukla yazılan tembel Prim'de if (agacta[e[1]]) continue; satırı silinirse ne olur?

Doğru: B. v ağaca girdikten sonra v'ye giden eski kayıtlar kuyrukta kalır. Bu kontrol olmadan böyle bir kayıt çıktığında iki ucu da ağaçta olan bir kenar T'ye eklenir: döngü oluşur ve kapsayan ağaç bozulur.

Son

Bölüm 14: Çizgeler: Çalışma Soruları
Konu anlatımı: Çizgeler sunumu
1 / 1 Sercan KÜLCÜ, Tüm hakları saklıdır.