BFS nedir, kuyruk ile gerçekleme, seviye seviye dolaşma, ağırlıksız grafta en kısa yol bulma — adım adım görseller, karmaşıklık analizi ve C kodu.
🗂️ Veri Yapıları📅 22 February 2026👁️ 14 görüntülenme
BFS Nedir?
Genişlik Öncelikli Arama (BFS), bir grafı seviye seviye (katman katman) dolaşan algoritmadır. Başlangıç düğümünden başlar ve önce tüm 1-mesafe komşuları, sonra 2-mesafe komşuları, sonra 3-mesafe komşuları... şeklinde ilerler. Su yüzeyine atılan taşın yarattığı dalgalar gibi düşünülebilir — merkezdeki taş başlangıç düğümü, her dalga halkası bir seviyedir.
BFS — Genişlik Öncelikli
Önce yakın komşuları keşfet, sonra uzaklara ilerle. Veri yapısı: Kuyruk (Queue) — FIFO Sıra: seviye 0 → 1 → 2 → 3 → ...
DFS — Derinlik Öncelikli
Önce mümkün olduğunca derine in, tıkanınca geri dön. Veri yapısı: Yığın (Stack) — LIFO Sıra: bir dal sonuna kadar → geri → diğer dal
BFS üç renkle düğümleri izler: Wbeyaz = keşfedilmemiş, Ggri = kuyrukta (keşfedildi ama komşuları henüz işlenmedi), Bsiyah = tamamlandı (tüm komşuları işlendi).
BFS pseudocode: 1. Başlangıç düğümünü gri yap ve kuyruğa ekle 2. Kuyruk boş olana kadar tekrarla: a. Kuyruktan bir düğüm çıkar (dequeue) → mevcut b. Mevcut'un her beyaz komşusu için: — Komşuyu gri yap — Mesafesini güncelle: mesafe[komşu] = mesafe[mevcut] + 1 — Ebeveynini kaydet: ebeveyn[komşu] = mevcut — Kuyruğa ekle (enqueue) c. Mevcut'u siyah yap 3. Tüm erişilebilir düğümler ziyaret edildi ✓
Neden kuyruk (Queue)? FIFO yapısı sayesinde ilk keşfedilen düğümler ilk işlenir. Bu, dalgaların eşit hızda yayılmasını sağlar — seviye 1 tamamen bitmeden seviye 2'ye geçilmez. Stack kullanılsaydı derinlik öncelikli (DFS) olurdu!
Adım Adım — BFS Dolaşma
Referans grafımızda başlangıç düğümü = 0. Her adımda kuyruğun durumunu, hangi düğümün işlendiğini ve mesafe tablosunu takip edelim.
6dequeue(5) → 5'in komşuları: 2(siyah), 7(gri, atla) → yeni keşif yok 7dequeue(6) → 6'nın komşuları: 3(siyah) → yeni keşif yok 8dequeue(7) → 7'nin komşuları: 4(siyah), 5(siyah) → yeni keşif yok
Kuyruk:BOŞ
Ziyaret:0, 1, 2, 3, 4, 5, 6, 7
Kuyruk boş → BFS tamamlandı ✓. Tüm düğümler ziyaret edildi.
BFS Sonuç — Mesafe ve Ebeveyn Tablosu
Düğüm
Mesafe
Ebeveyn
Seviye
BFS Sırası
0
0
—
0
1.
1
1
0
1
2.
2
1
0
1
3.
3
1
0
1
4.
4
2
1
2
5.
5
2
2
2
6.
6
2
3
2
7.
7
3
4
3
8.
BFS — C Implementasyonu
Kuyruk Yapısı
BFS kuyruğa dayanır. Basit bir dairesel kuyruk (circular queue) yeterlidir — en fazla V eleman tutabilir.
/*
* BFS — Genişlik Öncelikli Arama
* graf: komşuluk listesi (önceki bölümdeki ListeGraf)
* baslangic: kaynak düğüm
* mesafe[]: her düğümün kaynaktan mesafesi (-1 = ulaşılamaz)
* ebeveyn[]: BFS ağacında ebeveyn (-1 = kök veya ulaşılamaz)
*/voidbfs(ListeGraf* graf, int baslangic,
int mesafe[], int ebeveyn[]) {
int V = graf->dugumSayisi;
// 1) Başlangıç durumu: tümü keşfedilmemişbool* ziyaret = calloc(V, sizeof(bool));
for (int i = 0; i < V; i++) {
mesafe[i] = -1;
ebeveyn[i] = -1;
}
// 2) Kaynak düğümü başlatKuyruk* q = kuyrukOlustur(V);
ziyaret[baslangic] = true;
mesafe[baslangic] = 0;
enqueue(q, baslangic);
// 3) Ana döngüwhile (!kuyrukBos(q)) {
int u = dequeue(q);
// u'nun tüm komşularını taraKomsulukNode* komsu = graf->listeler[u];
while (komsu) {
int v = komsu->hedef;
if (!ziyaret[v]) { // beyaz → gri
ziyaret[v] = true;
mesafe[v] = mesafe[u] + 1;
ebeveyn[v] = u;
enqueue(q, v);
}
komsu = komsu->next;
}
// u artık siyah (tüm komşuları işlendi)
}
free(ziyaret);
free(q->veri);
free(q);
}
Karmaşıklık Analizi
Ölçüt
Komşuluk Listesi
Komşuluk Matrisi
Zaman
O(V + E) ✓
O(V²)
Bellek
O(V) (kuyruk + ziyaret + mesafe)
O(V)
Açıklama
Her düğüm 1 kez kuyruktan çıkar (V). Her kenar en fazla 2 kez kontrol edilir (E).
Her düğüm için tüm V sütunu taranır (V×V).
O(V + E) neden optimal? Grafı dolaşmak için her düğüme (V) ve her kenara (E) en az bir kez bakmak zorunludur. BFS tam olarak bunu yapar — ne fazla ne eksik. Bu yüzden BFS asimptotik olarak optimal bir dolaşma algoritmasıdır.
Seviye Seviye Dolaşma (Level-Order)
BFS'in doğal özelliği: düğümleri keşfedildikleri seviyeye göre gruplar. Bu özellik kullanılarak her seviyedeki düğümler ayrı ayrı işlenebilir — ağaç dolaşmadaki level-order traversal'ın graf versiyonudur.
bfs_seviye.c — seviye seviye dolaşma
voidbfsSeviye(ListeGraf* graf, int baslangic) {
int V = graf->dugumSayisi;
bool* ziyaret = calloc(V, sizeof(bool));
Kuyruk* q = kuyrukOlustur(V);
ziyaret[baslangic] = true;
enqueue(q, baslangic);
int seviye = 0;
while (!kuyrukBos(q)) {
int seviyeBoyut = q->son - q->bas; // bu seviyedeki düğüm sayısıprintf("Seviye %d: ", seviye);
for (int i = 0; i < seviyeBoyut; i++) {
int u = dequeue(q);
printf("%d ", u);
KomsulukNode* k = graf->listeler[u];
while (k) {
if (!ziyaret[k->hedef]) {
ziyaret[k->hedef] = true;
enqueue(q, k->hedef);
}
k = k->next;
}
}
printf("\n");
seviye++;
}
}
BFS ağacı: ebeveyn kenarları. Her düğümün kökten mesafesi = seviye numarası. Bu ağaç en kısa yol ağacıdır.
En Kısa Yol (Ağırlıksız Graf)
BFS'in en güçlü özelliği: ağırlıksız grafta en kısa yolu garanti eder. BFS her düğümü ilk keşfettiğinde, o düğüme minimum kenar sayısı ile ulaşılmış olur. Çünkü BFS seviye seviye ilerler — seviye k'daki tüm düğümler, seviye k+1'den önce keşfedilir.
Neden BFS en kısa yolu bulur? BFS seviye 0'dan başlar → seviye 1 → seviye 2 → ... Bir düğüm ilk kez seviye k'da keşfedildiyse, ona tam k kenarla ulaşılmıştır. Daha kısa bir yol olsaydı (k-1 veya daha az), düğüm daha önceki bir seviyede keşfedilirdi — ama keşfedilmedi. Bu çelişki kanıtlar ki BFS mesafesi minimumdur.
Yol Geri İzleme (Path Reconstruction)
BFS'in ebeveyn[] dizisi, kaynak düğümden herhangi bir düğüme en kısa yolu geri izlemek için kullanılır. Hedeften başlayıp ebeveyn takip ederek kaynağa ulaşılır, sonra yol ters çevrilir.
bfs_yol.c — en kısa yol bulma ve yazdırma
/* En kısa yolu geri izle ve yazdır */voidenKisaYolYazdir(int ebeveyn[], int mesafe[],
int baslangic, int hedef) {
if (mesafe[hedef] == -1) {
printf("%d → %d: ulaşılamaz!\n", baslangic, hedef);
return;
}
// Hedeften kaynağa doğru geri izleint yol[1000], uzunluk = 0;
int curr = hedef;
while (curr != -1) {
yol[uzunluk++] = curr;
curr = ebeveyn[curr];
}
// Ters çevirerek yazdırprintf("%d → %d (mesafe: %d): ",
baslangic, hedef, mesafe[hedef]);
for (int i = uzunluk - 1; i >= 0; i--) {
printf("%d", yol[i]);
if (i > 0) printf(" → ");
}
printf("\n");
}
En Kısa Yol Örnekleri — 0'dan Hedeflere
0 → 7:0→1→4→7mesafe = 3 ✓
0 → 5:0→2→5mesafe = 2 ✓
0 → 6:0→3→6mesafe = 2 ✓
0 → 1:0→1mesafe = 1 ✓
Her yol ebeveyn[] dizisinden geri izlenerek bulundu. Tüm yollar minimum kenar sayısına sahip.
Ağırlıklı graflarda BFS çalışmaz! BFS kenar sayısını minimize eder, kenar ağırlıklarının toplamını değil. Ağırlıklı graflarda en kısa yol için Dijkstra (pozitif ağırlıklar) veya Bellman-Ford (negatif ağırlıklar) kullanılmalıdır.
Demo — Tam Program
bfs_demo.c — tam çalışan program
intmain() {
// Referans grafı oluştur (8 düğüm, yönsüz)ListeGraf* g = listeGrafOlustur(8, false);
listeKenarEkle(g, 0, 1, 1);
listeKenarEkle(g, 0, 2, 1);
listeKenarEkle(g, 0, 3, 1);
listeKenarEkle(g, 1, 4, 1);
listeKenarEkle(g, 1, 2, 1);
listeKenarEkle(g, 2, 5, 1);
listeKenarEkle(g, 3, 6, 1);
listeKenarEkle(g, 4, 7, 1);
listeKenarEkle(g, 5, 7, 1);
// BFS çalıştırint mesafe[8], ebeveyn[8];
bfs(g, 0, mesafe, ebeveyn);
// Sonuçları yazdırprintf("=== BFS Sonuçları (kaynak: 0) ===\n");
printf("Düğüm | Mesafe | Ebeveyn\n");
printf("-------+--------+--------\n");
for (int i = 0; i < 8; i++)
printf(" %d | %d | %d\n",
i, mesafe[i], ebeveyn[i]);
// En kısa yolları yazdırprintf("\n=== En Kısa Yollar ===\n");
for (int hedef = 1; hedef < 8; hedef++)
enKisaYolYazdir(ebeveyn, mesafe, 0, hedef);
// Seviye seviye dolaşmaprintf("\n=== Seviye Seviye ===\n");
bfsSeviye(g, 0);
return0;
}
Bir sayfadan başlayıp tüm bağlantılı sayfaları keşfet
Önce yakın sayfalar → giderek uzaklara
Bağlılık kontrolü
Grafta tüm düğümler bağlı mı? Kaç bileşen var?
BFS'ten sonra ziyaret edilmemiş düğüm varsa → bağlı değil
Labirent çözme
Girişten çıkışa en kısa rota
2D grid = graf, her hücre = düğüm, 4 komşu
İki parçalılık testi
Graf bipartite mi? (2-renklendirilebilir mi?)
BFS ile 2-renkleme dene: çelişki varsa bipartite değil
Ağ yayılımı
Virüs/bilgi yayılımı simülasyonu
Her "tur" bir seviye = bir zaman adımı
GPS/Navigasyon (hop sayısı)
Minimum aktarma sayısı (uçuş, metro)
Her kenar = 1 aktarma → BFS optimal
Özel Durum — Bağlılık Bileşenleri
bağlılık bileşenleri — BFS ile
intbagliBilesenSay(ListeGraf* graf) {
int V = graf->dugumSayisi;
bool* ziyaret = calloc(V, sizeof(bool));
int bilesen = 0;
for (int i = 0; i < V; i++) {
if (!ziyaret[i]) {
// Yeni bileşen! BFS ile hepsini ziyaret etint mesafe[V], ebeveyn[V];
bfs(graf, i, mesafe, ebeveyn);
// BFS'in ziyaret ettiği düğümleri işaretlefor (int j = 0; j < V; j++)
if (mesafe[j] != -1) ziyaret[j] = true;
bilesen++;
}
}
free(ziyaret);
return bilesen;
}
Sonuç
BFS, grafı seviye seviye (genişlik öncelikli) dolaşan temel algoritmadır. İç yapısında kuyruk (FIFO) kullanır — ilk keşfedilen düğüm ilk işlenir. Bu basit prensip, BFS'e ağırlıksız grafta en kısa yol bulma garantisi verir: bir düğüm ilk kez keşfedildiğinde, o düğüme minimum kenar sayısı ile ulaşılmış olur.
Algoritma her düğümü ziyaret edilmiş olarak işaretleyerek sonsuz döngüyü önler. Komşuluk listesi ile zaman karmaşıklığı O(V + E) — asimptotik olarak optimal'dir. Ebeveyn dizisi sayesinde en kısa yol geri izlenebilir, seviye takibi ile katman katman işleme yapılabilir.
BFS'in uygulama alanları çok geniştir: en kısa yol, sosyal ağ önerileri, web crawling, bağlılık kontrolü, labirent çözme, bipartite testi ve ağ yayılımı simülasyonu. BFS ağırlıksız grafta en kısa yolu bulurken, ağırlıklı graflar için Dijkstra veya Bellman-Ford gerekir.
Bölüm 8.2.1 özeti:BFS = genişlik öncelikli arama. Kuyruk (FIFO) kullanır, seviye seviye ilerler. Algoritma: başlangıcı kuyruğa koy → kuyruk boşalana kadar: dequeue(u), u'nun her beyaz komşusu v için: mesafe[v]=mesafe[u]+1, ebeveyn[v]=u, enqueue(v). Karmaşıklık: O(V+E) zaman, O(V) bellek — optimal. En kısa yol garantisi: BFS seviye seviye ilerler → ilk keşif = minimum mesafe (ağırlıksız). Yol geri izleme: ebeveyn[] ile hedeften kaynağa. Uygulamalar: ağırlıksız en kısa yol, sosyal ağ önerisi (2. derece bağlantı), web crawler, bağlılık bileşenleri, labirent, bipartite testi. Sınırlama: ağırlıklı grafta çalışmaz → Dijkstra kullanılmalı. Sonraki bölüm: DFS (Derinlik Öncelikli Arama).