Algoritma Geliştirme ve Veri Yapıları 8 Kuyruk ve Yığın Yapısı
Yığın ve kuyruk modelleri verinin geçici olarka saklandığı, davranışları birbirinin tamamen tersi olan ve bellek üzerinde kurulmuş birer saklama mekanizmasıdır. Kuyruk modelinde, kuyruğa daha önce giren veri daha önce alınır; yani ilk giren ilk çıkar (First In First Out FIFO). Yığın veri modelinde ise, yığına son giren veri önce çıkar; burada da son giren ilk çıkar(last In First Out LIFO).
Koy Al Yığın Son giren ilk çıkar LIFO Ekle Kuyruk İlk giren ilk çıkar FIFO Çıkart
Yığın ve kuyruk modelinde gereksinim duyulan üç temel işlem vardır; o Ekleme o Alma o Sıfırlama/boşaltma Bunların dışında içerisindeki eleman sayısını sorgulayan, boş veya dolu olup olmadığını sınayan işlemlere de gereksinim duyulur. Ekleme işlemi yığında koy, kuyrukta ekle; alma işlemi yığında al, kuyrukta çıkart ve sıfırlama işlemi her ikisinde de sıfırla, temizle gibi sözcüklerle ifade edilir.
Kuyruk ve Yığın Yapısı
1)Kuyruk Yapısı Kuyruk, ilk giren ilk çıkar(first In First Out) mantığıyla çalışan ve bellek üzerinde kurulan bir mekanizmadır. Kuyruk modeli, program tasarımında birçok yerde kullanılır. İşletim sistemleri bünyesinde öncelik kuyruğu, yazıcı kuyruğu gibi birçok uygulama alanı vardır.
1)Kuyruk Yapısı Kuyruk tasarımı çeşitli şekillerde gerçekleştirilebilir. Biri, belki de en yalın olanı, bir dizi ve bir indis değişkeni kullanılmasıdır. Dizi gözlerinde yığına atılan veriler tutulurken indis değişkeni kuyruğa eklenen son veriyi işaret eder. Kuyruktan alma/çıkarma işlemi her zaman için dizinin başı olan 0 indisli gözden yapılır. Kuyruk tasarımı için üç değişik çözüm şekli vardır: o Dizi üzerinde kaydırmalı (Bir indis değişkenli) o Dizi Üzerinde Çevrimsel (İki indis değişkenli) o Bağlantılı Liste ile
1)Kuyruk Yapısı Her bir çözümün ihtiyaç duyulacağı uygulamalar vardır. Ancak dizi üzerinde kaydırmalı, her alma işleminde kuyruktaki veri sayısından bir eksik kaydırma işlemine gerek duyar. Kuyruktan alma işlemi zaman maliyeti artar. Onun yerine dizi üzerinde çevrimsel çözüm daha iyi sonuç verir. Kuyruğun bilgisayar belleğinde yer olduğu sürece genişletilmesi istenirse bağlantılı listeyle çözüme başvurulabilir.
Kuyruk ve Yığın Yapısı
1)Kuyruk Yapısı Dizi üzerinde kuyruk tasarımı verilerin bütünüyle bir dizi üzerinde tutulmasına dayanır; tutulacak toplam veri sayısı kadar boş bir bellek alanı bu iş için ayrılır. Veri yapısına uygun miktarda bellek alanı dizi bildirimi yapılarak ya da dinamik olarak oluşturulur. Tasarımda dikkat edilmesi gereken noktalar, kuyruğun boş veya dolu olması durumda işaretçi indis değişkenlerinin alacağı değerlerdir.
Kuyruk ve Yığın Yapısı
1.1 Dizi Üzerinde Kaydırmalı N uzunluğundaki bir dizi üzerinde kaydırmalı kuyruk yapısının davranışı önceki sayfadaki şekilde gösterilmiştir. o a) kuyruğun boş hali o b) herhangi bir andaki hali o c) dizinin ilk gözünden çıkartma işlemi yapılmış hali o d) kuyruğa ekleme işlemi
int cikart(){ if(son<0){ cout<< Kuyruk Boş! <<endl; return NULL; veri=k[0]; for(k=1;k<=son;k++) K[k-1]=K[k]; son--; return veri; int ekle(int veri) { son++; if(son>n){ cout<< Kuyruk Dolu <<endl; son--; return NULL; K[son]=veri;
1.1 Dizi Üzerinde Kaydırmalı Karmaşıklık kaydırma işleminden dolayı O(son), kuyruğun dolu olmaya yakın durumunda da karmaşıklık O(N), ancak ekleme işlemi karmaşıklığı O(1) dir.
1.2 Bağlantılı Liste ile Kuyruk Tasarımı Kuyruğun bağlantılı liste şeklindeki tasarımında ise, yine iki tane işaretçi vardır, bunlar da ilk ve son olarak adlandırılır. Ekleme işlemi son adlı verinin arkasına, kuyruktan alma işlemi de ilk ile gösterilen verinin alınması ve kuyruktan çıkarılmasıyla yapılır. Bu yaklaşımda kuyruğun boş olması demek ilk adlı işaretçinin NULL olmasıyla anlaşılır. Kuyruğun, eğer herhangi bir sınırlama getirilmemişse, dolu olması diye bir şey söz konusu değildir; dinamik bellek kullanıldığı için bilgisayarın belleğinde yer olduğu sürece kuyruk uzayabilir.
Kuyruktan çıkarma işlemi listenin başından, ekleme işlemi ise son ile işaret edilen ve kuyruğun sonunu gösteren düğüme yapılır.
int kuyruk(int veri, char mod) { static KUYRUKDUGUM *ilk=null, *son=null; int d; switch(mod){ case k : /*Koyma islemi*/ if(p= (KUYRUKDUGUM *)malloc(sizeof(kuyrukdugum))==null ) {cout<< Bellekte yer yok! <endl; return NULL; p->veri=veri; p->arka=null; if(ilk==null){ ilk=p; son=p;else{ son->arka=p; son=p; break; case a : /*Alma islemi*/ if(ilk==null) {cout<< Kuyruk Bos! <<endl; return NULL; p=ilk; ilk=ilk->arka; if(ilk==null) son=null; d=p->veri; free(d); return d;
case t : /*Kuyrugu temizleme-bosaltma islemi*/ while(ilk!=null){ p=ilk; ilk=p->arka; free(p); son=null; break; default: return NULL;
Bağlantılı Listeyle Öncelikli Kuyruk Bu yöntemde kullanılan veri yapısı içerisinde öncelik değerini içeren bir değişken kullanılmaktadır. Ekleme işleminde eklenecek yer bu öncelik değerine göre yapılmaktadır. son ilk ali 0 veli 1 mine 2 veli 1 son ilk ali 0 veli 1 ekleme mine 2
2) Yığın Tasarımı Yığın, ilk giren son çıkar veya diğer bir deyişle son giren ilk çıkar (Last In First Out) mantığıyla çalışan ve bellek üzerinde kurulan bir mekanizmadır; kendi içerisinde bir yığın işaretçisi(stack pointer) vardır ve bu herhangi bir anda ekleme yapılabilecek boş bir yığın gözünü gösterir. Yığına veri koyma işlemi yığın işaretçisinin gösterdiği göze yapılırken yığından veri alma, bu işaretçinin o anda gösterdiği yerin bir öncesinde yapılır.
Kuyruk ve Yığın Yapısı
2) Yığın Tasarımı Yığın tasarımı çeşitli şekillerde yapılır; en temelde birisi dizi üzerinde, diğeri bağlantılı listeyle yığın kurulmasıdır. Bağlantılı liste veri modeliyle gerçekleştirilen yığında tam bir dinamik çözüm vardır. Yığın, bilgisayarın belleğinde yer olduğu sürece genişleyebilir. Dizi kullanıldığında, eğer statik dizi bildirimi yapılmışsa yığın dolacağından yeni veri koyulamaz. Bu durumda ya yığından veri alınması beklenmelidir ya da yığının tutulduğu dizi tablo yönteminde yapıldığı gibi dinamik olarak genişletilmelidir.
2.1 - Dizi Üzerinde Yığın Tasarımı Bu yöntem verinin geçici olarak tutulacağı yerin bütünüyle bir dizi olarak bildirilmesine dayanır; tutulacak toplam veri sayısı kadar boş bir bellek alanı bu iş için ayrılır. Dizi üzerinde yığın tasarımın yığına koyma(push) ve yığından alma(pop) işlemleri örnek kodları söyledir;
/* Global bildirimler */ #define N 500 int Yveri[N]={0, yi=0; /* Yığına koyma fonksiyonu */ int koy(int veri) { if(yi>=n) puts("yığın Dolu"); return NULL; else { Yveri[yi]=veri; yi++; /* Yığından alma fonksiyonu */ int al() { if(yi<=0) { puts("yığın Boş"); return NULL; else return Yveri[--yi]; /* Yığını temizleme fonksiyonu */ void temizle() { yi=0;
2.1 - Dizi Üzerinde Yığın Tasarımı Eğer yığın işaretçisi yi, yığının toplam kapasitesini gösteren N den büyük veya eşitse yığın doludur; tersi durumda yi=0 ise yığın boş olarak değerlendirilir. Koy() isimli fonksiyonda görüleceği gibi ekleme yi ile işaret edilen göze yapılmakta ve yi nin değeri bir sonraki gözü gösterecek biçimce arttırılmaktadır. Al() isimli fonksiyonda da önce yığın işaretçisi bir önceki gözü gösterecek biçimde azaltılmakta ve önceki gözün içeriği gönderilmektedir. Temizle() fonksiyonu ile amaç yığının gözlerini boşaltıp başlangıç durumuna getirmektir.
#define EnFazla birtamsayi; struct Yyapisi{ unsigned int yi; verituru Yveri[EnFazla]; //verituru olarak istenilen tip yazılabilir Y; int koy(verituru veri) { if(y.yi>=enfazla) cout<< Yigin Dolu <<endl; return NULL; else{ Y.Yveri[Y.yi]=veri; Y.yi++; verituru al(){ if(y.yi<=0){ cout<< Yigin Bos! <<endl; return NULL; else{return Y.Yveri[--Y.yi]; void temizle(){ Y.yi=0;
2.2 Bağlantılı Listeyle Yığın Tasarımı Bu yöntem yığına atılacak her bir ayrık verinin bağlantılı liste şeklinde tutulmasına dayanır. Yığına veri koyma ve yığından veri alma listenin başından yapılabileceği için yürütme zamanı ve karmaşıklığı oldukça iyidir; karmaşıklığı her iki işlem için de O(1) olur. Bir alma işlemi yapıldığında listenin başındaki verilir; dolayısıyla alma işlemi bağlantılı listenin ilk düğümünü koparma ve içeriğini gönderme işlemidir. Yığına koyma işlemi de, yeni gelen verinin dinamik olarak düğümünü oluşturma ve listenin başına ekleme işlemidir.
Kuyruk ve Yığın Yapısı
int yigin(int veri, char mod) { Static yigindugum *yi=null; yigindugum *g,*v; if (mod== a ) //alma { if(yi==null) return NULL; g=yi; v.veri=yi->veri; yi=yi.arka; free(g); return v.veri; else{ //koy-ekle g=(yigindugum *)malloc(sizeof(yigindugum)); if(g==null) return NULL; g->veri=veri; g->arka=yi; yi=g;