Skip to main content

🧱 C Programlama ile Yığın (Stack) Yapısı Nasıl Uygulanır?

Bu rehberde, C programlama dilinde en temel veri yapılarından biri olan Yığın (Stack)’i sıfırdan nasıl oluşturacağınızı adım adım öğreneceksiniz.
Sabit boyutlu dizi tabanlı ve dinamik bağlı liste tabanlı iki farklı yöntemi de kod örnekleriyle göreceksiniz.
Ayrıca, her iki yöntemin performans farklarını, hata yönetimini ve pratikte hangi senaryoda hangisinin daha uygun olduğunu da inceleyeceğiz.


🎯 Bu Rehberde Ne Öğreneceksiniz?

  • Yığın (Stack) kavramının nasıl çalıştığını ve LIFO (Son Giren İlk Çıkar) mantığını anlayacaksınız.
  • C dilinde yerleşik Stack veri tipi olmadığını ve bu yüzden nasıl kendiniz tanımlayabileceğinizi göreceksiniz.
  • push, pop, peek, isEmpty, isFull işlemlerinin nasıl yazıldığını öğreneceksiniz.
  • Dizi tabanlı ve bağlı liste tabanlı uygulamaları karşılaştıracak ve bellek yönetimi hatalarından kaçınmayı öğreneceksiniz.

🧠 Yığın (Stack) Nedir?

Yığın, Son Giren İlk Çıkar (LIFO) prensibiyle çalışan bir veri yapısıdır.
En son eklenen eleman, ilk çıkar.
Bunu bir tabak yığını gibi düşünebilirsiniz — tabağı en üste koyar, en üsttekini alırsınız.

C dilinde stack yapısı yerleşik değildir, bu yüzden kendi veri yapınızı oluşturmanız gerekir.
Bu esneklik, hem dizi (sabit boyutlu) hem de bağlı liste (dinamik boyutlu) yaklaşımlarını öğrenmeyi zorunlu kılar.


⚙️ Stack İşlemleri ve Zaman Karmaşıklığı

İşlemTanımSüre (Big O)
push()Yığına yeni eleman eklerO(1)
pop()Tepedeki elemanı çıkarırO(1)
peek()Tepedeki elemanı görüntülerO(1)
isEmpty()Yığın boş mu?O(1)
isFull()Yığın dolu mu? (dizi tabanlı)O(1)

🔹 1️⃣ Dizi (Array) Tabanlı Yığın Uygulaması

Dizi tabanlı yaklaşımda yığın, sabit boyutlu bir diziyle temsil edilir.
Performansı yüksektir, ancak kapasitesi önceden belirlenmelidir.
Bu yöntemde taşma (Stack Overflow) riskine karşı kontrol yapılmalıdır.

Yapı Mantığı

  • top: Dizideki en üst elemanın indeksini tutar.
  • capacity: Maksimum eleman sayısını belirtir.
  • array: Dinamik olarak ayrılmış bellekte elemanları tutar.

Dizi Tabanlı Yığın Kodu

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

struct Yigin {
int top;
unsigned capacity;
int* array;
};

struct Yigin* yiginOlustur(unsigned capacity) {
struct Yigin* yigin = (struct Yigin*)malloc(sizeof(struct Yigin));
if (!yigin) return NULL;
yigin->capacity = capacity;
yigin->top = -1;
yigin->array = (int*)malloc(yigin->capacity * sizeof(int));
if (!yigin->array) { free(yigin); return NULL; }
return yigin;
}

int isFull(struct Yigin* yigin) { return yigin->top == yigin->capacity - 1; }
int isEmpty(struct Yigin* yigin) { return yigin->top == -1; }

void push(struct Yigin* yigin, int item) {
if (isFull(yigin)) { printf("Hata: Stack Overflow\n"); return; }
yigin->array[++yigin->top] = item;
printf("%d yigina eklendi\n", item);
}

int pop(struct Yigin* yigin) {
if (isEmpty(yigin)) { printf("Hata: Stack Underflow\n"); return INT_MIN; }
return yigin->array[yigin->top--];
}

int peek(struct Yigin* yigin) {
if (isEmpty(yigin)) { printf("Yigin bos\n"); return INT_MIN; }
return yigin->array[yigin->top];
}

💡 Bu örnek, dizi tabanlı bir yığının temel push, pop ve peek işlemlerini gösterir.

Çıktı Örneği

10 yigina eklendi
20 yigina eklendi
30 yigina eklendi
En ustteki eleman: 30
30 yigindan cikarildi
Hata: Stack Overflow

🔹 2️⃣ Bağlı Liste (Linked List) Tabanlı Yığın Uygulaması

Bağlı liste yöntemi, dinamik boyut avantajı sunar. Bellek dolmadığı sürece yığın büyüyebilir veya küçülebilir.

Mantık Her Node, bir veri (data) ve bir sonraki düğüme işaretçi (next) içerir.

top pointer’ı, en son eklenen düğümü işaret eder.

push işlemi, yeni bir düğüm oluşturur ve top’a bağlar.

pop işlemi, top düğümünü siler ve belleği free() ile temizler.

Bağlı Liste Tabanlı Yığın Kodu

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

struct YiginDugumu {
int data;
struct YiginDugumu* next;
};

void push(struct YiginDugumu** top_ref, int data) {
struct YiginDugumu* yeni = (struct YiginDugumu*)malloc(sizeof(struct YiginDugumu));
if (!yeni) { printf("Hata: Heap Overflow\n"); return; }
yeni->data = data;
yeni->next = *top_ref;
*top_ref = yeni;
printf("%d yigina eklendi\n", data);
}

int pop(struct YiginDugumu** top_ref) {
if (!*top_ref) { printf("Hata: Stack Underflow\n"); return INT_MIN; }
struct YiginDugumu* temp = *top_ref;
int cikarilan = temp->data;
*top_ref = (*top_ref)->next;
free(temp);
return cikarilan;
}

💡 Bu yöntem esnektir, ancak her düğüm ek bellek (pointer) gerektirir.


⚖️ Yöntem Karşılaştırması

ÖzellikDizi Tabanlı YığınBağlı Liste Tabanlı Yığın
BoyutSabitDinamik
HızDaha hızlı (cache dostu)Biraz yavaş
Bellek KullanımıAzFazla (pointer overhead)
Overflow RiskiVarYok
Uygulama KarmaşıklığıBasitOrta

💡 Performans açısından dizi tabanlı yöntem daha hızlıdır; ancak dinamiklik gerekiyorsa bağlı liste tercih edilir.


🧩 Yaygın Hatalar

top değişkenini yanlış güncellemek (top++ yerine ++top gibi).

Overflow/Underflow kontrollerini ihmal etmek.

free() çağrısını unutmak (Memory Leak).

NULL pointer erişimi (Segmentation Fault).


🧠 En İyi Uygulamalar

Her işlemden önce isEmpty / isFull kontrolü yapın.

size_t veya unsigned int türlerini tercih edin.

Kodunuzu modüler hale getirin (stack.h, stack.c).

Tutarlı hata mesajları ve geri dönüş değerleri kullanın.


❓ Sıkça Sorulan Sorular (SSS)

1️⃣ Stack ve Queue arasındaki fark nedir?

Stack: LIFO (Son Giren İlk Çıkar) — push/pop işlemleri tepe üzerinden yapılır. Queue: FIFO (İlk Giren İlk Çıkar) — enqueue/dequeue uçlardan yapılır.

2️⃣ Stack Overflow nedir?

Dolu bir yığına eleman eklemeye çalışmaktır. Array tabanlı yapılarda oluşur; push öncesi kontrol edilmelidir.

3️⃣ Stack ve Heap farkı nedir?

Stack (çağrı yığını) otomatik bellektir; fonksiyonlar ve yerel değişkenler tutulur. Heap ise dinamik bellektir; malloc/free ile yönetilir.

4️⃣ Bellek sızıntısı nasıl oluşur?

pop işlemi sonrası free() çağrısı unutulursa, silinen düğüm bellekte kalır. Bu durum uzun çalışmalarda bellek dolmasına neden olur.

5️⃣ Hangi yöntemi seçmeliyim?

Kapasite belliyse dizi tabanlı, değilse bağlı liste tabanlı stack en uygunudur.


🚀 Sonuç

Artık C dilinde stack (yığın) veri yapısını iki farklı yöntemle nasıl oluşturacağınızı biliyorsunuz. Performans açısından hızlı dizi tabanlı yaklaşımı veya esnek bağlı liste tabanlı yöntemi seçebilirsiniz. Bellek yönetimi, hata kontrolü ve modüler yapı konularını uygulayarak profesyonel stack uygulamaları geliştirebilirsiniz.

💬 Rabisu Bulut platformunda hemen deneyin — C projelerinizi çalıştırın, yığın yapınızı test edin ve performans farklarını canlı olarak görün!