CodeBlanks Logo Icon CodeBlanks

Özet - Dinamik veri

  • C kursu
  • Orta seviye
  • Ders 75/116
  • 5 dk

Bağlı liste, yığın ve kuyruğu birleştirerek bir geri-al/yinele sistemi yazarsın.

Özet - Dinamik veri

Bu grupta bağlı listeyi baştan kurduk: düğüm tanımı, başa ekleme, gezip yazdırma, silme ve dizi tabanlı yığın. Şimdi tüm parçaları bir araya getireceğiz.

Mini görev: 10 -> 20 -> 30 listesi kur, yazdır, ortadaki 20'yi sil, tekrar yazdır ve tüm belleği iade et. Bu, gerçek bir C programında dinamik verinin tipik yaşam döngüsüdür: kur, kullan, değiştir, temizle. malloc ile ayrılan her düğüm free ile iade edilmelidir; unutulursa sızıntı oluşur. Gezme döngüsü cur = cur->next ile ilerler; NULL görünce durur.

Uygulama Tüm parçaları birleştir

list_push_front, list_print ve list_remove işlevlerini yaz. main'de 30, 20, 10 değerlerini başa ekle; list_print(head); çağır; head = list_remove(head, 20);; tekrar list_print(head);; son olarak while (head) { Node *t = head; head = head->next; free(t); } ile tüm belleği iade et.

Başlangıç kodu

main.c
#include <stdio.h>
#include <stdlib.h>

typedef struct Node {
    int data;
    struct Node *next;
} Node;

// list_push_front: başa ekle
// list_print: gezerek yazdır
// list_remove: value'yu sil
// main: 30, 20, 10 ekle; yazdır; 20'yi sil; yazdır; tümünü free et

int main(void) {
    // buraya yaz
    return 0;
}

Örnek çözüm

main.c
#include <stdio.h>
#include <stdlib.h>

typedef struct Node {
    int data;
    struct Node *next;
} Node;

Node *list_push_front(Node *head, int v) {
    Node *n = malloc(sizeof(Node));
    n->data = v; n->next = head;
    return n;
}

void list_print(Node *head) {
    Node *cur = head;
    while (cur) { printf("%d ", cur->data); cur = cur->next; }
    printf("\n");
}

Node *list_remove(Node *head, int v) {
    if (!head) return NULL;
    if (head->data == v) { Node *t = head; head = head->next; free(t); return head; }
    Node *prev = head, *cur = head->next;
    while (cur) {
        if (cur->data == v) { prev->next = cur->next; free(cur); return head; }
        prev = cur; cur = cur->next;
    }
    return head;
}

int main(void) {
    Node *head = NULL;
    head = list_push_front(head, 30);
    head = list_push_front(head, 20);
    head = list_push_front(head, 10);
    list_print(head);
    head = list_remove(head, 20);
    list_print(head);
    while (head) { Node *t = head; head = head->next; free(t); }
    return 0;
}

Beklenen çıktı

10 20 30 
10 30

Dinamik veride dikkat

Dinamik veri güçlüdür ama dikkat ister. Üç temel ilke: her malloc'a bir free, iade edilen belleği bir daha kullanma, listeyi değiştirirken başın değişme olasılığını unutma.

Silme işlevi her zaman yeni başı döndürmelidir; çağıran da head = list_remove(head, x); ile geri almalıdır. Bu desen, başın silinmesi olasılığına karşı koruma sağlar. Gezme sırasında düğümü free edip sonra cur->next okumak hatalıdır; önce next'i sakla, sonra free yap. Yığın ve kuyruk, bu desenlerin dizilerle yapılan basit varyantlarıdır; aynı ilkeler geçerlidir.

Soru ve cevaplar

Dersin sorularını cevaplarıyla birlikte inceleyebilirsin. Kendini denemek istersen dersi interaktif olarak çöz.

1 Liste yaşam döngüsü

Kavram Anlamı
kur push_front ile
yazdır list_print ile
sil list_remove ile
temizle free ile

2 Listeyi tamamen temizlemek için ne yapılır?

  • head = NULL yazmak yeter
  • sadece ilk düğümü free et
  • list_print çağır
  • her düğümü free ile iade et Doğru cevap

Açıklama: Her malloc'a karşılık bir free gerekir.

Orta seviye bölümündeki tüm dersler