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