Linked List (Bağlı Liste)

İstersen buraya tıklayarak açıklamalı linked list kodunu indirebilirsin..

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


/**
* Çift Yönlü Bağli Liste Yapısı
* @author Yunus Emre AK
*/


typedef struct node{
int veri;

struct node *oncesi;
struct node *sonrasi;
}Dugum;

/**
* İkili Bağlı listede veriler bir önceki ve bir sonraki veririnin adresini tutar.
* []-[]-[]-[]-[] (bagli liste)
*
* Fonksiyonlarla işlem yaparken;
* Dugum* (Dugumun adresi)= Düğümlerle işlem yapmak için
* Dugum** (Bağlı Listenin adresi) = Bağlı Listeyle işlem yapmak için
* kullanılır.
*
* Fonksiyonlarla değerlerde değişiklik yapmak için, değerin adresini vermek gerekir.
*/

/**
* Alınan bağlı listenin en sonuna düğüm oluşturup veriyi ekleyen fonksiyon
* Fonksiyonlar aldıkları parametreleri kopyalığı için, bağlı listenin adresini
* tutan bir pointer almamız lazım.
*/
void append(Dugum **bagliListe, int veri){

// Yeni düğüm oluşturup, hafızadan yer atıyoruz.
Dugum *yeniDugum = (Dugum*)malloc(sizeof(Dugum));

// Düğüme veri atıyoruz.
yeniDugum->veri = veri;

/**
* Düğümün en sonuna ekleneceği için düğüm yapısı şu şeklildedir;
*
* ... - (yeniDugum) - NULL
*/

// Düğümün sonrası da, öncesi de null olduğu için atamaları yapıyoruz.
yeniDugum->sonrasi = NULL;

/**
* Eğer düğüm boş ise, öncesinde de eleman olmayacağı için NULL atıyoruz.
* NULL - (yeniDüğüm) - NULL
*/
if(*bagliListe == NULL){
yeniDugum->oncesi = NULL;

// Yeni düğümümüzü ana düğüme ekliyoruz.
*bagliListe = yeniDugum;

//Fonksiyon sonu.
return;
}

/**
* Dugumun en sonuna yeni dugum ekleneceği için, en sonunu bulmak için yardımcı
* düğüm oluşturuyoruz ki ana düğüm üzerinde değişiklik olmasın.
*/
Dugum *sonDugum = *bagliListe;

/**
* Yeni düğüm, düğüm sonuna ekleneceği için düğümü en sonuna alıyoruz.
* Düğüm son düğümünün sonrası NULL olacağı için, son düğüm NULL olana kadar bir
* sonrakinne geçiyoruz.
*/
while(sonDugum->sonrasi != NULL)
sonDugum = sonDugum->sonrasi;

/**
* Düğümün en sonu bulunduktan sonra düğüm yapısı şu şekilde olacaktır;
*
* (sonDugum) - (yeniDugum) - NULL
*/

// Yeni düğüm, son düğümün sonrasında olacağı için atama yapıyoruz.
sonDugum->sonrasi = yeniDugum;

// Son düğüm, yeni düğümün öncesinde olacağı için atama yapıyoruz.
yeniDugum->oncesi = sonDugum;

/**
* sonDugum'ü daha kullanmayacağımız için alttaki atamaya gerek yoktur.
* Yeni düğüm artık en sonda olacağı için son atamayı yapıyoruz.
* sonDugum = yeniDugum;
*/


// Fonksiyon sonu
return;
}

/**
* Alınan bağlı listenin en başına düğüm oluşturup veriyi ekleyen fonksiyon
* Fonksiyonlar aldıkları parametreleri kopyalığı için, bağlı listenin adresini
* tutan bir pointer almamız lazım.
*/
void push(Dugum **bagliListe, int veri){
// Eklenecek düğümü oluşturuyoruz.
Dugum *yeniDugum = (Dugum*)malloc(sizeof(Dugum));

// Düğüme veriyi atıyoruz.
yeniDugum->veri = veri;

/**
* Eklenecek düğüm en başa ekleneceği için, bağlı liste şöyle olacaktır;
*
* NULL - (yeniDüğüm) - ...
*/

// Yeni düğümün öncesi NULL olacağı için atama yapıyoruz.
yeniDugum->oncesi = NULL;

/**
* Eğer bağlı listede eleman yoksa yapı şöyle olacaktır;
*
* NULL - (yeniDüğüm) - NULL
*/
if(*bagliListe == NULL){
// Yeni düğümün sonrasında NULL olacağı için atama yapıyoruz.
yeniDugum->sonrasi = NULL;

// Yeni düğümü bağlı listeye atıyoruz.
*bagliListe = yeniDugum;

// Fonksiyondan çıkış
return;
}

// NOT: Bağlı listeden aldığımız düğüm değerinin değişmemesi için kopyalamlıyız.

// Bağlı listenin en önünü bulmak için geçici düğüm tanımlıyoruz.
Dugum *enOn = *bagliListe;



/**
* En öndeki elemanın bağlı listedeki konumu şöyle olacaktır;
*
* NULL - (enOn) - ...
* Bu yüzden enOn adlı düğümü öncesi NULL olana kadar öncekine atıyoruz.
*/
while(enOn->oncesi != NULL)
enOn = enOn->oncesi;

/**
* Eklenecek düğüm en başa ekleneceği için, bağlı liste şöyle olacaktır;
*
* NULL - (yeniDüğüm) - (enON)
* Not: yeniDugum'ün öncesine NULL ataması yukarıda yapılmıştı.
*/

// enON, yeniDugum'ün sonrasında olacağı için atama yapıyoruz.
yeniDugum->sonrasi = enOn;

//yeniDugum, enOn'un öncesine olacağı için atama yapıyoruz.
enOn->oncesi = yeniDugum;

/**
* enOn düğümünü daha kullanmayacağımız için alttaki atamaya gerek yoktur.
* Yeni düğüm artık en önde olacağı için son atamayı yapıyoruz.
* enOn = yeniDugum;
*/

// Fonksiyon sonu.
return;
}



/**
* Bağlı listeye eleman ekleme fonksiyonu.
* Bu fonksyion listeden her hangi bir düğümün adresini ve yerleştirilecek veriyi
* parametre olarak alıyor, bu sayede veri alınan düğümün sonrasına ekleniyor.
*/
void insertAfter(Dugum *elimizdekiDugum, int veri){
// İlk olarak düğümün doluluğu kontrol edilir, eğer boş ise işlem yapılmaz.
if(elimizdekiDugum == NULL){
printf("\n Dugumde veri bulunmamaktadir, hata !\nPush(param) fonksiyonunu kullaniniz.");


// Hata
return;
}
// Verinin ekleneceği yeni düğüm oluşturuyoruz.
Dugum *yeniDugum;

// Oluşturulan bu düğüm yeni bir düğüm olduğu için bellek atıyoruz.
yeniDugum = (Dugum*)malloc(sizeof(Dugum));

// Veriyi yeni düğümün verisine ekliyoruz.
yeniDugum->veri = veri;

/**
* Eklenecek olan yeni düğüm, parametre olarak verdiğimiz düğüm ile ondan sonraki
* düğüm arasına ekleneceği için, parametre olarak verdiğimiz düğümün sonrasındaki
* düğümün bilgisi de bize lazım olacaktır. Bu sebeple sonrakinin verisi tutan bir
* düğüm daha oluşturuyoruz.
*/
Dugum *sonrakiDugum;

/**
* Bu düğüm yeni bir düğüm olmayacağı için bellek atamıyoruz, elimizdeki düğümün
* sonrasındaki düğümün adresini atıyoruz.
*/
sonrakiDugum = elimizdekiDugum->sonrasi;


/**
* Eklenecek olan yeni düğüm, elimizdeki düğüm ile onun sonrasındaki düğümün arasına
* eklenceği gerekli atamaları yapıyoruz;
*
* (elimizdeki düğüm) - (yeni düğüm) - (elimizdekinden sonraki düğüm)
*/

// Yeni düğüm, elimizden sonraki düğümden önce olduğu için atama yapıyoruz.
if(sonrakiDugum != NULL)
sonrakiDugum->oncesi = yeniDugum;

// Elimizden sonraki düğüm, yeni düğümden sonra geldiği için atama yapıyoruz.
yeniDugum->sonrasi = sonrakiDugum;

// Elimizdeki düğüm, yeni düğümden önce olduğu için atama yapıyoruz.
yeniDugum->oncesi = elimizdekiDugum;

// Yeni düğüm, elimizdeki düğümden sonra geldiği için atama yapıyoruz.
elimizdekiDugum->sonrasi = yeniDugum;

// Fonksiyondan çıkış.
return;

}

/**
* Düğüm silme fonksiyonu
*
* Bu fonksiyon paremetre olarak aldığı silenecek düğümü silip, içindeki veriyi
* paremetre olarak aldığı veriAdresi'ne atıyor.
*
* NOT: Bu fonksiyonu kullanırken doğrudan düğümün adresini göndermeyin, gönderdiğiniz düğüm
* silineceği için bağlı listeye olan erişiminiz kesilecektir. Bu sebeple parametre olarak
* düğümün öncesini (prev) veya sonrasını (next) gönderin.
*/
void delete(Dugum *silinecekDugum, int *veriAdresi){
// Öncelikle düğüm doluluğunu kontrol ediyoruz, boş ise işlem yapılamaz.
if(silinecekDugum == NULL){
printf("Silecek dugum bulunmamakta, hata!");

// Fonksiyondan çıkış.
return;
}

/**
* İlk olarak silinecek düğümdeki veriyi alıyoruz. Veri adresi bir adres olduğu
* için, *(veriAdresi) yaparak, veri adresinin değerine atıyoruz.
*/
*veriAdresi = silinecekDugum->veri;

/**
* Düğümü silmeden önce öncesindeki ve sonrası düğüm arasındaki bağlantıyı
* oluşturmamız lazım, be sebeple önceki ve sonraki düğüm adi altında 2 düğüm oluşturuyoruz.
*
* (önceki düğüm) - (silenecek düğüm) - (sonraki düğüm)
*/
Dugum *oncekiDugum,*sonrakiDugum;

// Silinecek düğümden önceki düğümü oluşturuyoruz.
oncekiDugum = silinecekDugum->oncesi;

// Silinecek düğümden sonraki düğümü oluşturuyoruz.
sonrakiDugum = silinecekDugum->sonrasi;

// Düğümü siliyoruz.
free(silinecekDugum);

/**
* Düğüm silindikten sonra, düğümün yeni yapısı şu şekilde olacak;
* (önceki düğüm) - - (sonraki düğüm)
*/

// Önceki düğüm, sonraki düğümden önce geldiği için atama yapıyoruz.
if(sonrakiDugum != NULL)
sonrakiDugum->oncesi = oncekiDugum;

// Sonraki düğüm, önceki düğümden sonra geldiği için atama yapıyoruz.
if(oncekiDugum != NULL)
oncekiDugum->sonrasi = sonrakiDugum;

// Fonksiyondan çıkış.
return;
}

/**
* Verileri gösterme fonksiyonu
* Alınan düğümün öncesindeki ve sonrasındaki her bir veriyi gösterir.
*/
void display(Dugum *dugum){
// Öncelikle veri kontrolü yapıyoruz.
if(dugum == NULL){
printf("\n Verilen dugum bostur, hata!");

// Fonksiyondan çıkış.
return;
}

// Döğüm üzerinde gezinmek ve alınan düğüm adresini kaybetmemek için gezici tanımlıyoruz.
Dugum *gezici = dugum;

printf("\n-> Dugumdeki veri:\n%d",gezici->veri);
printf("\n---------\n-> Dugumden sonraki veriler:\n");

// Sonrasında veri olduğu sürece, verileri ekrana yazdırılmasını sağlıyoruz.
while(gezici->sonrasi != NULL){
// Düğümü bir sonrasındakine eşitleyerek, sonraki düğüme geçiyoruz.
gezici = gezici->sonrasi;

printf("%d, ", gezici->veri);
}

// NULL olan geziciyi, tekrardan düğüme eşitliyoruz.
gezici = dugum;

printf("\n-> Dugumden onceki veriler:\n");

// Öncesinde veri olduğu sürece, verileri ekrana yazdırılmasını sağlıyoruz.
while(gezici->oncesi != NULL){
// Düğümü bir öncekine eşitleyerek, önceki düğüme geçiyoruz.
gezici = gezici->oncesi;

printf("%d, ", gezici->veri);
}

printf("\n---------");
// Fonksiyondan çıkış.
return;
}

int main(){
Dugum *deneme = NULL;

int i;
int veri;

for(i = 0; i < 10; i++){
if(i%4 == 0)
push(&deneme, i);
else if(i%4 == 1)
append(&deneme, i);
else if(i%4 == 2)
insertAfter(deneme->sonrasi, i);
else if(i%4 == 3){
delete(deneme->sonrasi, &veri);
printf("----\n Silinen veri: %d",veri);
}
display(deneme);
}

}
Veri Yapıları

Yorumlar

Popüler Yayınlar