Sorting (Sıralama) Algoritmaları: Radix(Redux) Sort

Yeni başlamamıza ve pek zaman bulup yazamasakta gelen yorumlar ve istekler üstüne insan ne işle ilgilenirse ilgilensin, elindekini bir kenara itip hemen sevdiği ve ilgilenmek istediği işe yöneliyor. Sanırım insanı bundan daha çok mutlu edebilecek bir şey olamaz.Gel gelelim, Radix sort nedir?

Radix Sort Mantığı Ve Pratik Örnek:

Radix sort, Bucket sort algoritması taban alınarak ortaya çıkmıştır. Hane sıralaması olarakta adlandırılabilir. En değersiz haneden (Least Significant Digit), en değerli haneye (Most Significant Digit) doğru sıralama işlemi yapılır. Mümkün oldukça açıklayıcı olacağına inandığım bir örnekle devam edelim…

…Öncelikle sıralanmamış bir kaç sayı dizisi oluşturalım.

  • 170
  • 45
  • 43
  • 80
  • 24
  • 902
  • 2

Birler(1) hanesine göre sıralama yaptığımız zaman elimize geçicek dizi şu şekilde olucaktır;

  • 170
  • 80
  • 902
  • 2
  • 43
  • 24
  • 45

*Burda dikkat edilmesi gereken en büyük hususlardan biri de, birler(1) basamağına göre sıraladığımızda basamağın içeriği dizi içindeki herhangi bir sayı ile aynı ise sıralanmamış listedeki sıraya göre dizilmeleridir. 170 sayısının 80 sayısından önce gelmesinin sebebi budur.

Ikinci basamağa göre sıralamaya geçtiğimiz zaman sıralamamız şu şekilde olucaktır;

  • 902
  • 2
  • 24
  • 43
  • 45
  • 170
  • 80

Ardından son basamağımıza(3 üncü) göre sıraladığımızda ise;

  • 2
  • 24
  • 43
  • 45
  • 80
  • 170
  • 902

Görsel olarak daha  açıklayıcı imajlar yardımı ilede anlatılabilinicek bu konu için Google Images ‘den de yardım alınabilir.

Radix Sort Implementasyonu:

Bu sıralama mantığımızı bir de implemente ederek, kod tarafında anlaşılır kılalım. Bir çok mantık kullanılarak yazılabilecek bu sort algoritmasının özellikle Link List’de verimli olacağını düşünüyorum, ancak daha basit bir örnekle anlatılması gerektiğini düşündüğümden ötürü sadece fonksiyon özellikleri kullanarak bu örneği sunacağım. Kayıt altında tuttuğum bir kod örneği;

Kaynak Kod:

/* Written by Sanchit Karve (born2c0de)
 Contact Me at born2c0de AT dreamincode DOT net
*/

#include <stdio.h>
#include <conio.h>

#define MAX 8
#define SHOWPASS

void print(int *a,int n)
{
 int i;       
 for(i=0;i<n;i++)
 printf("%d\t",a[i]);
}

void radixsort(int *a,int n)
{
 int i,b[MAX],m=0,exp=1;
 for(i=0;i<n;i++)
 {
 if(a[i]>m)
 m=a[i];
 }

 while(m/exp>0)
 {
 int bucket[10]={0};
 for(i=0;i<n;i++)
 bucket[a[i]/exp%10]++;
 for(i=1;i<10;i++)
 bucket[i]+=bucket[i-1];
 for(i=n-1;i>=0;i--)
 b[--bucket[a[i]/exp%10]]=a[i];
 for(i=0;i<n;i++)
 a[i]=b[i];
 exp*=10;

#ifdef SHOWPASS
 printf("\nPASS   : ");
 print(a,n);
#endif
 }       
 }

int main()
{
 int arr[MAX];
 int i,n;

 printf("Enter total elements (n < %d) : ",MAX);
 scanf("%d",&n);          

 printf("Enter %d Elements : ",n);
 for(i=0;i<n;i++)
 scanf("%d",&arr[i]);

 printf("\nARRAY  : ");
 print(&arr[0],n);

 radixsort(&arr[0],n);

 printf("\nSORTED : ");
 print(&arr[0],n);
 printf("\n");
 getch();
 return 0;
}

*Kod içeriğinde minik ve önemsiz değişiklikler yapmış bulunmaktayım.

murproject

Yorumlar (0) |Etiketler: , , , , ,
seperator

Sıralama (Sorting) Algoritmaları ve Karşılaştırmalar

Sıralama algoritması, bilgisayar bilimlerinde ya da matematikte kullanılan, verilen bir listenin elemanlarını belirli bir sıraya sokan algoritmadır. En çok kullanılan sıralama türleri, sayı büyüklüğüne göre sıralama ve alfabetik sıralamadır. Sıralama işleminin verimli yapılması, arama ve birleştirme algoritmaları gibi çalışması için sıralanmış dizilere gereksinim duyan algoritmaların başarımının yüksek olması için önemlidir. Sıralama algoritmaları bilgisayarlarda tutulan verilerin düzenlenmesini ve insan kullanıcı tarafından daha rahat algılanmasını da sağlar.

Sıralama algoritmaları, tanımı çok yalın olmasına karşın çözümü çok karmaşık olan bir işi gerçekleştirdikleri için, üzerinde en fazla araştırma yapılan bilgisayar bilimi konularından biridir. Çoğu kişi sıralama sorununu çözülmüş bir sorun olarak görse de, yeni sıralama algoritmaları üzerinde araştırmalar sürmektedir. Örneğin kütüphane sıralaması ilk olarak 2004 yılında ortaya atılmıştır. Sıralama algoritmaları, sayılarının çok olması ve değişik yaklaşımlar sunmaları nedeniyle özellikle giriş düzeyindeki bilgisayar bilimleri derslerinde büyük O gösterimi ve veri yapıları gibi temel algoritma kavramlarının açıklanması amacıyla yaygın biçimde kullanılırlar.

Bilgisayar bilimlerinde kullanılan sıralama algoritmaları genellikle aşağıdaki ölçütlere göre sınıflandırılır:

  • Hesaplama karmaşıklığı: Dizideki öğelerin karşılaştırılmasının en iyi, ortalama ve en kötü başarımının dizinin boyutu (n) cinsinden gösterilmiş halidir. Olağan uygulamalarda sıralama algoritmalarının iyi durum başarımı O(n log n) ve kötü durum başarımı is Ω(n²)’dir. Bir sıralama algoritmasının istenen karmaşıklığı O(n)’dir. Yalnızca soyut bir anahtar karşılaştırması yapan bütün sıralama algoritmaları en kötü durumda her zaman Ω(n log n) karşılaştırma yaparlar.
  • Yer Değiştirme Karmaşıklığı (yerinde sıralama algoritmaları için).
  • Bellek (ve diğer donanım kaynaklarının) Kullanımı: Bazı sıralama algoritmaları dizinin içerdiği öğelerin dizinin saklandığı alanda sıralar. Böylece sıralanan öğeler dışında yalnızca O(1) ya da O(log n)’lik bir ek bellek alanı gerekir. Bazı algoritmalar ise verinin geçici olarak saklanması için dizinin tutulduğu alanın dışında ek bellek alanlarına gereksinim duyar.
  • Özyineleme: Bazı algoritmalar ya özyinelemeli ya da özyinelemesiz çalışırken, birleştirmeli sıralama gibi bazı algoritmalar iki biçimde de uygulanabilir
  • Kararlılık
  • Kaşılaştırma sıralaması olup olmama: Bir karşılaştırma sıralaması sıralanacak veriyi, bir karşılaştırma işlemi kullanarak, karşılaştırarak inceler.
  • Genel Yöntem: Araya sokma, değiştirme, seçme, birleştirme vb. Değiştirme sıralamalarına kabarcık sıralaması ve hızlı sıralama örnek olarak gösterilebilir.Yığın sıralaması ise seçme sıralamalarındandır.

Bu kategoriler dahilinde pek çok algoritma olmakla beraber bu algoritmaların genel olarak işleyiş, kullanım alanları ve elde edilen sonuçlar neredeyse tamamiyle koşullar dahilinde belirlenmekte olup, En iyi sıralama algoritması kavramı en azından günümüz için elde edilmesi pek muhtemel görünmeyen bir kavramdır denebilir.

Sıralama Algoritmaları

Sıralama Algoritmaları

Eklemeli (Insertion), Selection (Seçmeli) , Bubble (Kabarcık) , Shell (Kabuk) , Merge (Birleştirmeli), Heap (Yığın) , Quick (Hızlı) ve Quick3 algoritmalarını 4 ayrı koşul olan rastgele (random) , yaklaşık sıralı (nearly sorted) , ters (reversed) ve few unique ile ilgili birebir incelemeleri görmek ve animasyonlara ulaşmak içinse  bu adresi tavsiye edebilirim…

Aynı zamanda bellek, kararlılık ve diğer açıklamalarla ilgili, Sıralama Algoritmaları konu başlığı altında hazırlanmış Wikipedia Sayfası’nı da ziyaret edebilirsiniz..

Yorumlar (1) |Etiketler: , , , , , ,
seperator

Sorting (Sıralama) Algoritmaları: Bubble Sort

Sıralama algoritmaları, bilgisayar ve matematik dünyasının değişilmez algoritmalarıdır. Bu gözlemde bir çok sıralama algoritması oluşturulmuştur. Her birinin çalışma prensibi diğerinden farklı olması ile, değişik kullanım alanları ve verimlilik oranlarıda mevcuttur. Kullanıcı genelen kullanacağı algoritmayı kendisi, çalışacağı alana ve istediği performans kriterlerine göre seçer. Kaç tane algoritma olduğu sorusuna cevap olarak…

  • Bubble Sort
  • Insertion Sort
  • Shell Sort
  • Merge Sort
  • Heap Sort
  • Quick Sort
  • Bucket Sort
  • Radix Sort
  • Distribution Sort
  • Shuffle Sort

… gibi birçok sorting(sıralama) algoritması örneği verilebilir.

Ilk önce Bubble(baloncuk) sort(sıralama) algoritması üzerinde duralım. Birçok algoritmaya göre çok yavaş ve verimsiz çalışan bu algoritmanın mantığı dize içerisindeki ilk iki elemanı karşılaştırmak, büyük olanı elemanı küçük olanla yer değiştirmek(büyük olanı tepeye çıkarmak) ve böyle devam etmek. Sonrasında ise tekrar ilk iki elemanı karşılaştırarak dize sonuna kadar değişim yapmadan vardığında işlemini bitirmiş olucaktır.

Kod örneği…

/**
 **Author:Uğur Aydoğdu
 **Date:10.04.2009
 **Aim:Basic bubble sort algorithm for c++
 **/
 #include
 #include
 #define SIZE 5 //defining a size for our array (dizemiz için boyut belirliyoruz)

using namespace std;

int main(){
 int temp,i,j;
 int numbers[SIZE];
 for(i=0;i< SIZE; i++){
 cout << "Please enter the " << i+1  << ". number:";
 cin >> numbers[i];
 cout << endl;
 }

//bubble sorting
 for(i=0;i
 for(j=0;j
 if(numbers[i]>numbers[j])
 {
 int temp=numbers[i]; //swap(algortimamıza göre değişim yapıyoruz)
 numbers[i]=numbers[j];
 numbers[j]=temp;
 }

}

}
 //printing after sorting
 cout << "Sorted Array:\n";
 for(i=0;i
 cout << numbers[i];
 if(i!=(SIZE-1)){ cout<< ","; } // If it's the last item do not print ,
 }
 cout << "\nSmallest number is: " << numbers[SIZE-1]; // not the last
 cout << "\nLargest number is: " << numbers[0];

cin >> i; // wait before exit
 return 0;
 }

…üstteki gibi olmakla beraber, bilgisayarınızda test etmenizi ve kod örneğinin değişik varyasyonlarını yazmanızı tavsiye ederiz. Örnek olarak BubbleSort(degiskenDize) tipinde bir fonksiyon yaratarak bu işlemin bir fonksiyonun yapmasını sağlayabilirsiniz.

murproject

Yorumlar (5) |Etiketler: , ,
seperator

C ve C++ ile Toplama

Programlamaya ve C/C++ dillerine giriş yapan arkadaşların genellikle ödev veya çalışma sorusu olarak karşılarına çıkan ve fonksiyon kullanımı açısından ana mantığın oturtulması açısından önem taşıyan bu önemli konuya geçtiğimiz hafta içerisinde oluşturduğum kodları paylaşarak değinmek istedim.

Program içerisinde yaptıklarımız sırasıyla kullanıcıdan iki sayı almak ve belirlediğimiz değişkenlere atadıktan sonra, dışarıdan tanımladığımız sum (toplama) fonksiyonumuzu bu sayılarla çağırmaktan ibaret.

Kodlarımıza gelince:

C++ Kodu


#include
#include 

using namespace std;
int sum(int a,int b, int c){
int bigsum = a+b+c;
return bigsum;
}

int main(){
int a,b,c;
cout << "Ilk sayiyi girin:";
cin >> a;
cout << "Ikinci sayiyi girin:";
cin >> b;
cout << "Ucuncu sayiyi girin:";
cin >> c;

cout <<  a << " , " << b << " ve " << c << " sayilarinin toplami " << sum(a,b,c);
cin >> a; //wait
}

C Kodu

#include
#include 

int sum(int a,int b, int c){
int bigsum = a+b+c;
return bigsum;
}

int main(){
int a,b,c;
printf("Ilk sayiyi girin:");
scanf("%d",&a);
printf("Ikinci sayiyi girin:");
scanf("%d",&b);
printf("Ucuncu sayiyi girin:");
scanf("%d",&c);

printf("%d , %d ve %d sayilarinin toplami %d \n",a,b,c,sum(a,b,c));
system("pause");
}

Olursa, konu ile ilgili sorularınızı yorumlarınız aracılığıyla bildirebilirsiniz…

Teşekkürler

Yorumlar (1) |Etiketler: , , , , ,
seperator

Comment Yazmak

Temel…

Kaynak kod dökümantasyonu  temel bir yazılım mühendisliği kuralıdır. Getirileri ise verimli kod blokları yazmamızı sağlar. Yazarı tarafından ve ya diğer kullanıcılar tarafından tekrar kullanılabilmesi, üzerinde modifikasyonlar yapılabilmesi, direk değişimler ve ya bazı küçük ihtiyaçlar için gereklidir.

Comment…

Türkçe çevirisi yorum,  açıklama, eleştiri olan comment, kod blokları içerisinde kullanılarak her kesim tarafından anlaşılır, NL(National Language) seviyesine indirilmiş bloklar oluşturur. Resmi açıklamayı bir kenara koyarsak, kod okurken zorlandığımızı hissederiz, zorlanırız da. Bu zorlanmayı gidermek, yazılan kodun görev ve anlamlarını bilinir bir dile çevirmek asıl amacımız olmalı. Böylece kişisel ve ya bir birim adına çalışırken oluşturduğumuz kodların diğer kişisel tarafından anlaşılmasını sağlayarak, “software engineering ethics &fundementals” adı altında toplayabiliriz; Unutmayalım ki Dünyanın,yaşamın kuralı budur. Ne kadar ekmek o kadar köfte.

Kullanım alanları…

  • Kaynak kodlarının en tepesinde(yazar,zaman,amaç bilgileri v.b)
  • Sınıf(Class) başlarında(yazar,zaman,sınıf adı,kısa olarak amacı,belki yenimi yazıldı ve ya modifiye mi edildi bilgisi)
  • Fonksiyon(yazar,zaman,fonksiyonun adı,fonksiyonun amacı,aldığı argümanlar ve döndürdüğü değer)
  • İç kodlar(in-line code);

Bilmeliyiz ki her iç kod için comment yazmak saçma olur. Sonuçta anlayabileceğimiz bir kod satırı için comment yazılmamalıdır.Örnek vermek gerekise…

return deger; //degeri döndür

…ancak

/*
**push(struct Stack *,elemType ):(data type:void),(arguements:2)
**Author:Murat Ünal
**Date:10.10.2008
**Aim:push data into stack, create new node and assign data to nodes data.Check if stack member number is max 10.
*/
void push(struct Stack *mainStack,elemType data){
if(mainStack->size<maxElement){//if stack member is less than max element
struct Node *newNode=(struct Node *)malloc(sizeof(struct Node));
newNode->data=data;
printf("\npushing into stack...\t%d\n",newNode->data);
if(isEmpty(mainStack)){    //if it's the first element in stack
newNode->next=NULL;
mainStack->top=newNode;
}
else{
newNode->next=mainStack->top;
mainStack->top=newNode;
}
mainStack->size+=1;
}
}
else{//if stack is full
printf("\nYou can't push into stack more than %d element",maxElement);
}

Bu kod satırlarını daha anlaşılır hale getirmek için önceden girdiğim comment örneğini yayınlamak istedimBöylece hem anlaşılır hemde kafa karıştırmayan bir comment yaratmaya çalıştım.Unutmayalım ki comment yazmanın tam bir üslubu olmamakla birlikte, taşıdığı önem daha belirgindir.

murproject

Yorumlar (0) |Etiketler: ,
seperator

Open-Closed Kuralı(Principle)

OCP(Open-Closed Principle),eklenti yazılabilecek ancak,içerdiği kodu modifiye edemeyeceğimiz sınıf(class) yapıları oluşturmamızı sağlıyacak kuraldır.Elimizde herhangi bir sınıf olduğunu varsayarsak;bu sınıfın eski kodlarını değiştirmektense,yeni kodlar,methodlar yaratmamızı sağlar.Bu durumu gerçekleştirmemizi sağlayan bir kaç yardımcı araç bulunmaktadır.

  • Abstraction
  • Polymorphism
  • Inheritance
  • Interfaces

Yazdığımız her modülün OCP kuralına uymasını beklemeyebiliriz.Ancak bu kurala uymayan modül veya sınıfları mümkün olduğu kadar azaltabilme imkanlarımız mevcut.OO dizaynın(Object Orient) en yararlı kurallarından biridir.Ayrca OCP’nin tekrar kullanım(reusability) ve bakımı da(maintainability) kolaylaştırdığı bir gerçektir.

Örnek kod ile açıklamak gerekirse;


public double totalPrice(Part[] parts) {
double total = 0.0;
for (int i = 0; i < parts.length; i++) {
total += parts[i].getPrice();
}
return total;
}

bu fonksiyonun görevi,part sınıfı ile yaratılmış part array’i içindeki tüm parçaların fiyatlarını toplamak ve bunu döndürmesidir.Problemsiz işliyor gibi…

…peki diyelim ki parçalardan bir kaçının fiyatı değiştirildi.Kısacası indirim gerçekleşti.


public double totalPrice(Part[] parts) {
double total = 0.0;
for (int i=0; i < parts.length; i++) {
if (parts[i] instanceof Motherboard)
total += (1.45 * parts[i].getPrice());
else if (parts[i] instanceof Memory)
total += (1.27 * parts[i].getPrice());
else
total += parts[i].getPrice();
}
return total;
}

Çözüme bu şekilde de ulaşabiliriz.Sizcede kötü gözükmüyor mu ?

  • Her indirim ve ya zam durumu söz konusu olduğunda class yapısını değiştirmek zorundamı kalacağız?
  • OCP kuralına uymuyor gibi!!!

Biraz daha farklı yöntemler deneyerek;


/ Class Part is the superclass for all parts.
class Part {
private:
double price;
public:
Part(double price) (this.price = price;}
void setPrice(double price) {this.price = price;}
double getPrice() {return price;}
}
// Class ConcretePart implements a part for sale.
// Pricing policy explicit here!
class ConcretePart: public Part {
public:
double getPrice() {
// return (1.45 * price);              //Premium
return (0.90 * price);                 //Labor Day Sale
}
}

gibi iki sınıf elde edebiliriz.Elimizde bir adet baba sınıf,bir adette ondan türemiş çocuk class var.Böylece farklı parçalar için farklı fiyatlar belirleyebiliyoruz.Fakat hala bir sorun var.Her indirim ve zam döneminde bu sefer de parçaların fiyatlarını güncellemek zorunda kalıcaz.Hem eski kodumuzu değiştiricez,hem zaman kaybına uğrayacağız.Peki;


class Part {
private:
double price;
PricePolicy pricePolicy;
public:
void setPricePolicy(PricePolicy pricePolicy) {
this.pricePolicy = pricePolicy;
}
void setPrice(double price) {this.price = price;}
double getPrice() {return pricePolicy.getPrice(price);}
}

class PricePolicy {
private:
double factor;
public:
PricePolicy (double factor) {
this.factor = factor;
}
double getPrice(double price) {
return price * factor;
}
}

Fiyat politikası için ayrı bir sınıf yaratarak, her parçaya belirli bir fiyat politikası atayarak işlemleri uzatmadan ve karıştırmadan belirleyebiliriz.Böylece her fiyat politikası değişiminde,karışık yorumlar ve fiyatları kodların içinee serpiştirmeden,her parçaya fiyat politikasını “get” ve “set” metodları ile atayabilir,kullanılırlığı arttırabiliriz.

*Kod örneği Sayın Ufuk Çelikkan’ın  slaytlarından alıntıdır.

murproject

Yorumlar (1) |Etiketler: , , , ,
seperator

“Merhaba Dünya” - “Hello World” Arşivi

“Hello World” , yani “Merhaba Dünya!” konsepti hangi dili öğrenirsek öğrenelim, hepimizin ilk yazdığı ve ekranda görmeyi istediği kalıptır. Peki hiç merak ettik mi ilk Hello World nerededir? Nasıl yayınlanmıştır? Ne zaman yayınlanmıştır… diye? Evetleri duyuğumuza göre bu altın değerindeki bilgiyi paylaşıyorum. Ilk Hello World Kernighan & Ritchie’nin C programlama dili üzerine yazdığı kitabının 1.1 inci bölümünde ve 1978 yılında yayınlanmıştır.

main() {
printf("hello, world\n");
}

Bu başlangıç sonrasında, Hello World terimi neredeyse dünya üzerindeki tüm programlama dillerine uygulanmakla birlikte bu paylaşımda Hello World Collection üzerinde yayınlanmakta olan 412 Hello World programı ve aynı zamanda Türkçe’nin de dahil olduğu 63 insan dilinde Merhaba Dünya! dökümanından faydalandığımı da özellikle vurgulamak istiyorum.Sözü geçen ve bahsedilen tüm programlar kendi dilleri içerisinde yazılabildikleri en minimal şekilde paylaşılmış ve bu nedenle ait oldukları dillerin fonksiyonelliği hakkında çok detaylı bilgi verdikleri söylenemez. Fakat bu konu da aradan çıksın derseniz 1238 programlama dilini kapsayan 99 Bottles of Beer arşivini de incelemenizde şiddetle fayda var.

Bu yazıda kullandığım arşive gelince; proje, Wolfram Rösler tarafından dünyanın dört bir yanındaki programcıların katkılarıyla 3 Ekim 1994 yılında başlatılmış ve 30 Aralık 1999 yılında internette paylaşıma sunulmasına rağmen 200 girdi barajını ancak 2005 yılının ortalarında aşabilmiş. Yeni geçen 400 barajı için milat 27 Temmuz 2008 olarak kayıtlarda yer almakla beraber bu arşivin dünya üzerindeki insan dillerini de kapsayan tek ve en büyük Hello World Kaynağı olma özelliğini de taşıdığını sanıyorum. Orijinal liste ise Windows işletim sistemi üzerinde metin tabanlı dosyaların Cygwin altında çalışan bir bash script tarafından oluşturduğu HTML sayfa kullanılarak yaratılıyor…

Bu kadar konuşmadan sonra… Onca veriyi güncel olarak burada tutmaya çalışmak ve sayfayı koda boğmaktansa, yiğidi öldür hakkını deme diyerek sizi http://www.roesler-ac.de/wolfram/hello.htm adresine yönlendirmekten büyük keyif ve onur duyuyorum ve bu güzel şöleni kendi web sitem için düzenlediğim görsel ile süsleyerek herkese Degisken’den Merhaba diyorum…

Yorumlar (0) |Etiketler: , , , , , , , ,
seperator

Stack Veri Yapısı

Stack Nedir?

Stack,bir tür veri yapısıdır.Özetle bir konteynerdir.Modern bilgisayar sistemlerinin her seviyesinde kullanılabilmektedir.Ayrıca *LIFO kuralına göre çalışan bir data tipidir.Stackleri,üst üste sıralanmış tabaklar olarak düşünebiliriz;Yıkandıktan sonra tabak en üste konur,yemek koyabilmek için en üstteki tabak alınır.

Hardware Stack

Stack,memory de sabit bir bölümde,değişken boyutlarda bulunur.Genellikle başlangıçta stack boyutu sıfırdır.Stack boyutu sıfır iken stack pointer,stack başlangıç noktasının adresini tutar;Stack boyutu değiştiğinde ise stack pointer, her zaman aktif pencerelerin adresini tutar.Örneğin; Boyutu sıfır olan bir stack ele alırsak ve başlangıç adresinin 100 olduğunu varsayarsak;Eklediğimiz her veri boyutu kadar stack boyutu artıcaktır.Aynı zamanda stack pointer gelinen son adresi gösterecektir.

Stack Imaj(wikipedia)

Stack(wikipedia)

Software Stack

Yazılım açısından bakıldığı zaman stack,üst seviye programlama metodudur.Stack kullanarak verilerimizi belirli sırada saklayabilir,tekrar kullanabiliriz.Temiz bir çöp kutusu hayal edersek,içine ne atarsak atalım,elimizle içinden çekip alabileceğimiz öge her zaman en son attığımız olucaktır.Bu düşünceden yola çıkarsak,aklımızda bazı fikirler oluşucaktır.Örneğin;

  • pop (veri çıkarma)
  • push(veri koyma)
  • top(en üstteki veriye ulaşma)
  • empty(konteynerimizin boş olup olmadığını kontrol etme)

Elbette bu işlevsellikler dışında stack kurallarını bozmadan,aklımıza gelen fonksiyonları ekleyebiliriz.Ancak print() fonksiyonu bu kuralı ne kadar ihlal etse de kullanmaya ihtiyaç duyabiliriz.

Özetlememiz gerekirse;

  1. Stack yapısı kurabilir,bu yapının bazı node(veri blokları) nı tutmasına,onlar arasında gezmesine izin verebiliriz.
  2. Stack yapısının boş olup olmadığını öğrenebilir,en son koyduğumuz veri blokunun içeriğini çekebiliriz.
  3. Stack yapısının en üstüne ekleme yapabilir ve ya en üstteki veri blokunu çekebiliriz.
  4. Stack yapısının içinde tek tek gezerek bütün veri bloklarının tuttuğu verileri yazdırabiliriz.
  5. Veri bloklarında sadece veri tutabiliriz,bu verileri döndürebiliriz.
  6. Veri blokları arasında bağlantı oluşturabilir,böylece bloklar arasında gezmemizi kolaylaştırabiliriz.

gibi bazı fikirlerimizi belirleyip bunları requirement(ihtiyaç) listemizde tutarak, kodumuzu fazla komplex düşünmeden yazmaya başlayabiliriz.

//Author:Murat UNAL  -  murproject@gmail.com
//Language:C
#include <stdio.h>
#include <conio.h>;
#define maxElement 10
//
//Type Definition
//
typedef int elemType;
//
//Node:data container
//
struct Node{
elemType data;//node data
struct Node *next;//next pointer
};
//
//Stack:Node container
//
struct Stack{
elemType size;//size of Stack
struct Node *top;//next pointers

};
//
//Functions for structures
//     //
//initiliaze(void ):creates stack,initilies it's first data and returns it to main.(data type:struct Stack),(arguements:0)
//
struct Stack initiliazeStack(void){
struct Stack *mainStack;
mainStack=(struct Stack *)malloc(sizeof(struct Stack));
mainStack->size=0;
mainStack->top=NULL;
return *mainStack;
}
//
//push(struct Stack *,elemType ):will push data into stack max 10,create new node and initiliaze data into node's data. (data type:void),(arguements:2)

//
void push(struct Stack *mainStack,elemType data){
if(mainStack->size<maxElement){
struct Node *newNode=(struct Node *)malloc(sizeof(struct Node));
newNode->data=data;
printf("\npushing into stack...\t%d\n",newNode->data);
if(isEmpty(mainStack)){    //if it's the first element in stack
newNode->next=NULL;
mainStack->top=newNode;
}
else{
newNode->next=mainStack->top;
mainStack->top=newNode;
}
mainStack->size+=1;
}
else{
printf("\nYou can't push into stack more than %d element",maxElement);
}
}
//
//isEmpty(struct Stack*):will check stack if it has got any element inside and return 1/0.(data type:elemType),(arguements:1)
//Bug:datatype of function can be boolean.
//
elemType isEmpty(struct Stack*mainStack){
if(mainStack->top==NULL)
return 1;
else return 0;
}
//
//printStack(struct Stack*):will print the all node's data from top to bottom.(data type:void),(arguements:1)
//
void printStack(struct Stack*mainStack){
printf("\nprinting the stack...\n");
if(isEmpty(mainStack)) // if stack is empty
printf("\nYour Stack is Empty at the moment...\n");
else if (mainStack->size==1)//if just one element
printf("\n%d\n",mainStack->top->data);
else{
struct Node *walkerNode=(struct Node *)malloc(sizeof(struct Node));
for(walkerNode=mainStack->top;walkerNode->next!=NULL;walkerNode=walkerNode->next){
printf("\n%d\n",walkerNode->data);
}
printf("\n%d\n",walkerNode->data); //for last node's data preview
}

}
//
//pop(struct Stack*):will pop the top element from stack and preview it.(data type:elemType),(arguements:1)
//
elemType pop(struct Stack* mainStack){
if(isEmpty(mainStack)){// if stack is empty
printf("\nNot able to pop.Your Stack is Empty at the moment...\n");
}
else if(mainStack->size==1){//if just one element
printf("\npoping from stack...\t%d\n",mainStack->top->data);
free(mainStack->top);
mainStack->top=NULL;
mainStack->size-=1;
}
else{
struct Node* walkerNode=(struct Node*)malloc(sizeof(struct Node));
walkerNode=mainStack->top;
mainStack->top=walkerNode->next;
printf("\npoping from stack...\t%d\n",walkerNode->data);
free(walkerNode);
mainStack->size-=1;
}
}
//
//sizeOfStack(struct Stack*):will return the size of stack.(data type: elemtype),(arguements:1)
//
elemType sizeOfStack(struct Stack* mainStack){
return mainStack->size;
}

//
//Client(User):
//
int main(){
struct Stack *mainStack;
mainStack=(struct Stack *)malloc(sizeof(struct Stack));
*mainStack=initiliazeStack();
pop(mainStack);
push(mainStack,10);
pop(mainStack);
printStack(mainStack);
push(mainStack,10);
pop(mainStack);
push(mainStack,20);
pop(mainStack);
push(mainStack,30);
pop(mainStack);
push(mainStack,50);
pop(mainStack);
pop(mainStack);
pop(mainStack);
push(mainStack,50);
push(mainStack,60);
push(mainStack,70);
printStack(mainStack);
pop(mainStack);
pop(mainStack);
printStack(mainStack);
getch();
return 0;
}

Güvenlik

C dilinin veri ve prosedür çağrılarının geri dönüş adresleri için paylaşımlı stack kullanıyor olması ve gelen verinin boyutunu doğrulamaması sebebi ile güvenlik açığının meydana gelmesi mümkündür.Taşınan ve ya girilen veri, stack üzerinde yanlış bölüme aktarılırsa;Stack boyutunun kabul edemeyeceği bir veri girilmeye çalışılırsa,bu adreslerin bozulması,kaybolması ve programın düzgün çalışamaması mümkündür.

*LIFO(last in-first out):son giren,ilk çıkar.
murproject

Yorumlar (0) |Etiketler: , , ,
seperator

Selamla Değişkeni!

21 Kasım 2008 tarihinde aniden alınan karar ile server değiştirip,hacı hoca yeşili temamızdan kurtulup,daha sade ve göze hoş gelebilecek temamızı kurmuş bulunmaktayız. Ne yapacağımıza gelirsek, elimizden geldiği kadar hep beraber programlama ile ilgili ulaşabileceğimiz en fazla kişiye ulaşıp herkesin çözüm aradığı veya merak ettiği en genel terimlere, uygulamalara ve anlatımlara yer vermeye çalışacağız.

Ilerleyen zaman diliminde sizleri de aramızda görebilmek ve beraber nice kod bloklarının altına imza atabilmek dileğiyle.

Jnbn & murproject

Yorumlar (0) |Etiketler: ,
seperator