PDA

Tam Sürümünü Görmek İçin : stack uygulaması


RaiST
13/11/2002, 23:06
Buda basit bir stack uygulaması.
umarım bir işe yarıyordur..

stack.h

struct stack
{
float data;
struct stack *next;
};

typedef struct stack STACK;

STACK * Push(STACK * myStack,float value);
float Pop(STACK * myStack);
int isFull();
int isEmpty(STACK * myStack);



stack.c

#include <alloc.h>
#include "stack.h"

STACK * Push(STACK * myStack,float value)
{
STACK * new;
STACK * temp;
temp=myStack;
if (myStack==NULL)
{
new=(STACK*)malloc(sizeof(STACK));
new->next=NULL;
new->data=value;
myStack=new;
}
else
{

while(temp->next!=NULL)
{
temp=temp->next;
}
new=(STACK*)malloc(sizeof(STACK));
new->data=value;
new->next=NULL;
temp->next=new;
}

return myStack;

}

float Pop(STACK * myStack)
{
STACK * prev;
STACK * temp;
int val=0;

temp=myStack;
while(temp->next!=NULL & temp->next!=temp)
{
prev=temp;
temp=temp->next;
}


val=temp->data;


prev->next=NULL;
free(temp);



return val;
}

int isFull()
{
STACK * new;
if ((new=(STACK*)malloc(sizeof(STACK)))==NULL)
{
/* hafiza dolu!! */

return 1;

}
else
{
return 0;
}


}

int isEmpty(STACK * myStack)
{
if (myStack==NULL)
{
return 1;
}
else
{
return 0;
}



}





test.c

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include "stack.c"


/* Hseyin Uslu */

#define DEBUG_STACK 0
/* DEBUG_STACK=1 yaplrsa program her iŸlemden sonra stackin o anki halini g”sterecektir*/

void DebugStack(STACK *); /*Stack Debug fonksiyonu */

void main()
{

STACK * ourStack=NULL;
int i;
float deger;


clrscr();


for (i=1;i<=10;i++)
{
if (isFull()==0)
{
printf("%d. de§eri giriniz:",i);
scanf("%f",&deger);
ourStack=Push(ourStack,deger);
}
else
{
printf("Hazfa dolu! Stack i‡in yeni yer ayrlamyor...");
getch();
exit(0);
}


}

DebugStack(ourStack);
printf("\n---------- Stack library kullanlarak avarage hesaplanyor... ----------\n");



while(ourStack->next->next!=NULL)
{
if (isEmpty(ourStack)==0)
/*stack boŸ de§ilse */
{
Push(ourStack,Pop(ourStack)+Pop(ourStack));
DebugStack(ourStack);
}
}

Push(ourStack,Pop(ourStack)+Pop(ourStack));
DebugStack(ourStack);

printf("_____________________________________________\n");
printf("Avarage=%f",Pop(ourStack)/10);

getch();

}

void DebugStack(STACK * myStack) /*Stack Debug fonksiyonu */
/*stacking o anki durumunu ekrana yazdrr */
{
STACK * temp;

if (DEBUG_STACK==1)
{
temp=myStack;
printf("[DEBUG - printing current list : ");
printf("%.1f",temp->data);
while(temp->next!=NULL & temp->next!=temp)
{
temp=temp->next;
printf("->%.1f",temp->data);
}
printf("\n");
}


}


ee++
13/11/2002, 23:24
Agir elestiriler: :)

1- Kod gereksiz olarak uzun.
2- Kod standart degil.
3- Kod gelen amacli degil, sadece float degerler için Yığıt yapısı/işlevi sağlıyor.

Bu üçünü ortadan kaldırırsan güzel olur ve bunu gerçekleştirler var zaten, mesela C++ Standart Kütüphanesi..
:)

RaiST
13/11/2002, 23:29
ağır cevaplar: :):D

1- hoca /asistanların isteği üzerine yapılabilecek çoğu optimizasyon yapılmaıyor...
2- standartlara uyma yine yukardaki kişlerin istekleri üzerine yapılamıyor.. yaparsak, yanlış diye işin içinden çıkma durumları yüksek..
3- genel amaçlı değil yazacaktın galiba.
evet spesifik bir kod. ödev kağıdında belirtilen şekilde...

teşekkürler..

(bu arada bu standartizasyon !yanlış yazdım ehhe! konusunda bir ara görüşelim.. )

ee++
13/11/2002, 23:38
Orjinal mesajı gönderen RaiST
(bu arada bu standartizasyon !yanlış yazdım ehhe! konusunda bir ara görüşelim.. )

Bu konuda ee++ ve acehreli ile saatlerce süren hamam muhabbetleri yapabilirsin.. :) De mi acehreli? :)

RaiST
14/11/2002, 00:37
kısa zaman içinde inşallah:)

acehreli
19/11/2002, 21:00
Bu sıralar buraya fazla yazmıyorum ama okuyorum. :o)

Kodun doğru olması konusunda ee++'a katılıyorum. Ancak, nette (veya başka bir yerde, örneğin okulda :) gördüklerini ve duyduklarını her zaman için şüpheyle almak herkesin kendi sorumluluğu. Bu gibi forumlarda görülen kodlarda ne kadar çok yanlış bulunduğunu herhangi birisi bir kaç saatlik okumada anlıyor olmalı :) Tabii öyle olabilmesi için de başkalarının mutlaka yanlışları düzeltmeleri ve daha iyi yöntemler önermeleri gerekiyor. Forumların amacı da bu zaten :)

Ben de RaiST'in kodu üzerine bir şeyler yazayım:

- Push, myStack==NULL olduğunda kendisi bir stack oluşturuyor. Ben buna katılmıyorum. Push'u yasal olmayan bir stack'le çağırmak hata kabul edilmeli. Bu durumda ben olsam stack kuran ve bozan iki işlev yazardım. Örneğin


STACK * ConstructStack();
void DestructStack(STACK *);


- "isFull gereksiz. Nasıl olsa isEmpty var." Diyecektim ki, isFull'un bellekte yer olup olmadığını anlamaya çalışan bir işlev olduğunu farkettim :) Bu işlevin amacına ulaşması ancak tesadüfen olabilir. isFull 0 döndürse bile ondan sonra yer ayırmaya çalıştığımızda yer bulamayabiliriz. Ya da, isFull 1 döndürdüğünde onu boşverip yer almaya kalksak, yer bulabiliriz. Bunların nedeni, işletim sisteminde belleğin büyüklüğünün, o sırada çalışmakta olan işletim dizileri nedeniyle kıpır kıpır oynuyor olmasıdır. Yani bir an var olan şey, bir an sonra yok olabilir :)

- İki yerde, mantıksal VE işlemi (&&) yerine bit işlemi VE'nin (&) kullanıldığını gördüm. Örneğin:


while((temp->next!=NULL) & (temp->next!=temp))


(Okumayı kolaylaştırmak için fazla parantezleri kendim ekledim.)

Bu bağlamda, bit işleci kullanmanın bir sakıncası yok gibi gözüküyor, çünkü hem sol tarafın hem de sağ tarafın değerleri ya 1 ya da 0 olacak (sanırım).

Ama sonradan birisi gelip,


temp->next!=NULL


ifadesinin aslında mantıksal olarak


temp->next


ifadesine eşedeğer olduğu gerçeğini kullanıp o satırı şöyle değiş4irebilir:


while(temp->next & (temp->next!=temp))


Şimdi başımız belada. Çünkü her iki taraf da sıfır olmasa da, bit işleci '&' için kullanıldıklarında sonuç sıfır çıkabilir (örneğin, 2 & 1 = 0).

Ek olarak, mantıksal VE işlecinin kestirme kuralını kullanarak, gerekmedikçe sağ taraftaki ifadeyi işlememe şansı vardır. Yani daha hızlı olabilir.

Neyse, belki yalnızca küçük bir yanlışlık sonucu yazılmıştı ama bence mantıksal VE işleci (&&) kullanılmalı (iki yerde). Ayrıca, '!=NULL' kısmını kullanmamak da çok yaygın bir kullanım olduğundan, ben şunu yeğliyorum:


while(temp->next && (temp->next!=temp))


- Push'un içinde şöyle bir arama yapıyoruz: (linear search'ün Türkçe'si nedir?)


while(temp->next!=NULL)
{
temp=temp->next;
}


Eklenen nesneleri en sona koyacağımıza en başa koysak hem Push daha hızlı olur hem de Pop. Ayrıca stack kavramına da uyuyor. Hep üste koyar ve üstten alırız.


- isEmpty'ye bakınca sanki şöyle olması gerekiyor gibi geldi.


int isEmpty(STACK * myStack)
{
if (myStack.next==NULL)
{
return 1;
}
else
{
return 0;
}
}


Bunu da daha geleneksel olarak şöyle yazabiliriz:


int isEmpty(STACK * myStack)
{
return myStack.next == NULL;
}


Yani, sanki değeri NULL olan bir stack yasal olmamalı gibi geliyor. myStack doğru düzgün olmalı da, içindeki birşey NULL olmalı. "Peki o zaman bu durumda data'nın değerinin anlamı ne olacak?" diye düşünürken aslında burada bir düğüm yapısına daha gerek olduğunu düşünmeye başladım. stack yapısında stack'i ilgilendiren genel bilgiler, düğümde de her düğümü ilgilendiren şeyler olmalı:


struct dugum
{
float data;
struct dugum * next;
};

struct stack
{
unsigned int toplam_oge;
/* başka şeyler de olabilir */
/* örneğin istatistiksel bilgiler... */
/* ... */

struct dugum * top;
};


Evet, sanırım böyle olunca herşey daha mantıklı...

- 'void main' standart değildir. Onun yerine standart olan 'int main'i kullanabiliriz.

- 'avarage' yerine 'average' olacak... Ya da Türkçesi olan 'ortalama'yı kullanabiliriz.

- Kodun içine açıklamalar koymak iyidir. Ama daha iyisi, açıklamalara gerek bırakmayacak kadar açık kod yazmaktır. Örneğin isEmpty işlevi, hiç açıklamaya gerek bırakmayacak kadar açık. Adından kendisine verilen şeyin (bu durumda stack) boş olup olmadığını bildiren bir işlev olduğu anlaşılıyor. Yani, aşağıdaki açıklama gereksiz:


if (isEmpty(ourStack)==0)
/*stack boş değilse */


Hatta, '==0' diyeceğimize '!' işlevini de kullanabiliriz:


if (!isEmpty(ourStack))


Bazı insanlar o ünlem işaretinin çok zor görüldüğünü düşünerek etrafına boşluklar da koyarlar:


if ( ! isEmpty(ourStack))


Bunların dışında aslında gerçekten iyi. Anlaşılan ödev olarak da iş görüyor... :)

Ali