Jump to page: 1 2
Thread overview
Bağlı Liste başına ekleme yaptığımızda, bellekteki tüm veriler neden kayar?
Feb 20, 2012
Salih Dinçer
Feb 20, 2012
Salih Dinçer
Feb 21, 2012
zafer
Feb 21, 2012
Salih Dinçer
Feb 22, 2012
Salih Dinçer
Feb 22, 2012
Salih Dinçer
Feb 22, 2012
erdem
Feb 23, 2012
Salih Dinçer
Feb 23, 2012
erdem
Feb 24, 2012
Salih Dinçer
February 20, 2012

Öncelikle kodu veriyorum:

import std.array, std.conv, std.stdio, std.string;

struct AĞAÇ {
   int yaprak;
   AĞAÇ* sonrakiDal;

   this(int yaprak, AĞAÇ* sonrakiDal) {
       this.yaprak = yaprak;
       this.sonrakiDal = sonrakiDal;
   }
   void başınaEkle(int değeri, ref AĞAÇ* boğumu) {
       boğumu = new AĞAÇ(değeri, boğumu);
   }
   void ekle(int değeri, ref AĞAÇ* boğumu) {
       auto ekle = new AĞAÇ(değeri, null);
       boğumu.sonrakiDal = ekle;
       boğumu = ekle;
   }
   string toString() const {
       string tamamı = format("%d\t@%X", yaprak, &yaprak);
       if (sonrakiDal) tamamı ~= "\n" ~ to!string(*sonrakiDal);

       return tamamı;
   }
}

void main (){
   AĞAÇ* yedek, soy = new AĞAÇ(0, null);

   yedek = soy;
   foreach(r; 1..4) soy.ekle(r, yedek);

   writeln("AĞAÇdakiler~~~~~v\n", to!string(*soy));
   soy.başınaEkle(5, soy);
   writeln("AĞAÇdakiler~~~~~v\n", to!string(*soy));
}

Konu hakkında başka başlıkta tartışmıştık. Orada yazanları aynen ekliyorum. Tek yaptığım değişiklik, gereksiz şeyleri yansıtmayıp (ama sonuç adres değerleri dışında yine aynı!) ubyte yerine int'e geçmem. Tabi bellek değerleri arasında mesafe ne hikmetse yine aynı kalıyor. Yakında şu bağlı liste olayını anlayacağım ama hala şaşırıyorum ki taaa 1955'de ortaya atılan bir şeymiş...:)

Şu şekilde listemi oluşturuyorum: foreach(r; rakamlar) soy.ekle(r, yedek);

Çıktısı:

'AĞAÇdakiler~~~~~v
0 @BFB4E214
1 @BFB4E174
2 @BFB4E0D4
3 @BFB4E034'

ve bir güzel başına ekleme yapıyorum: soy.başınaEkle(5, soy); Kodu ise basit, şu:

void başınaEkle(ubyte değeri, ref AĞAÇ* boğumu)
{
   boğumu = new AĞAÇ(değeri, boğumu);
}

Bu durumda aynı çalışma anında bunun gibi ilginç bir sonuç çıkıyor:

'AĞAÇdakiler~~~~~v
5 @BFB4E214
0 @BFB4E174
1 @BFB4E0D4
2 @BFB4E034
3 @BFB4DF94'

Tamam, öngördüğümüz gibi başına ekliyor ama dikkat E214 ile biten 0 değerli eleman yerine başına eklediğim geliyor ve diğerleri aynı bellek değerleri ile aşağıya kayıyor! Allah Allah, bu nasıl bağlı liste? Eğer bütün dillerde böyle çalışıyorsa herhalde yavaş olur diye düşünmeden edemiyorum... :rolleyes:

Teşekkürler...

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

February 20, 2012

Yapıların değer türleri olduklarını konuştuk. Bunun işlevlere gönderilme durumlarında değerin kopyalanması anlamına geldiğini biliyoruz.

Yapı nesnelerinin birbirlerine eşdeğer kabul edilebilmeleridir. Derleyici nasıl 42 gibi bir değeri kopyaladığında kopyaların hepsi de 42 değerinde iseler yapı nesnelerini de istediği kopyalar ve o kopyalar birbirlerinin eşdeğeridir.

Nesne to!string'e gönderildiğinde de referans olarak değil, kopya olarak gönderiliyor. O yüzden dolaylı olarak kendi toString'imiz çağrıldığında yazdırdığımız &yaprak, geçici bir nesnenin üyesinin adresi oluyor. Eğer yaprağın adresini ekle() içindeki nesneyi oluşturduktan sonra yazdırırsan şimdiye kadar gördüklerinden çok farklı bir değer olduğunu göreceksin:

       auto ekle = new AĞAÇ(değeri, null);
       writefln("yeni oluşturdum: %s %s", ekle.yaprak, &(ekle.yaprak));

Çünkü o zaman new ile oluşturulmuş olan dinamik nesnenin içindeki üyenin adresini yazdırıyorsun. Yani merak etme, liste doğru oluşturuluyor. Sen farkında olmadan yerel kopyanın üyesinin adresini yazdırıyorsun.

Yalnız, ilgisiz ama çok önemli bir önerim var. NYP'de üye işlevlerin o anda üzerinde işlemekte oldukları nesne ile ilgili olmalarını bekleriz. Yani örneğin ekle() işlevi içinde iken bu nesnenin sonrakiDal isimli üyesinin değerinin değişmesini beklerim.

Buradaki ekle()'de ise parametre olarak gönderilen boğumu isimli nesneye ekleniyor. Alışılmışın çok dışında bir kullanım oluyor.

Bunu anlamak için toString() ile karşılaştırabiliriz: toString()'e boğumu diye bir parametre gönderip onun üyelerini yazdırmıyoruz. toString() içinde iken bu nesnenin üyelerini yaprak ve sonrakiDal olarak yazdırıyoruz.

ekle()'de ve başınaEkle()'de de öyle olmasını beklerim. Onlar ayrıca AĞAÇ almamalılar, üzerinde çağrıldıkları AĞAÇ nesnesini değiştirmeliler.

Ayrıca, ağaç olmayan bu yapının ismini fazla geciktirmeden Liste olarak değiştirmeni öneririm. ;)

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

February 21, 2012

Alıntı (Ali Çehreli):

>

Nesne to!string'e gönderildiğinde de referans olarak değil, kopya olarak gönderiliyor. O yüzden dolaylı olarak kendi toString'imiz çağrıldığında yazdırdığımız &yaprak, geçici bir nesnenin üyesinin adresi oluyor. Eğer yaprağın adresini ekle() içindeki nesneyi oluşturduktan sonra yazdırırsan şimdiye kadar gördüklerinden çok farklı bir değer olduğunu göreceksin:

> auto ekle = new AĞAÇ(değeri, null);
>         writefln("yeni oluşturdum: %s %s", ekle.yaprak, &(ekle.yaprak));
> ```

> Çünkü o zaman new ile oluşturulmuş olan dinamik nesnenin içindeki üyenin adresini yazdırıyorsun. Yani merak etme, liste doğru oluşturuluyor. Sen farkında olmadan yerel kopyanın üyesinin adresini yazdırıyorsun.
Şimdi daha iyi anlıyorum; en azından iki farklı bellek bölgesi (örn. bende @bf ile @b7 başlayanlar) aslında aynı şeyi gösterdiğini anlıyorum. Bir tek ekrana yazıldığı an farklı bir işlevden (örn. to!string) çağrılırsa başka bir yeri gösteriyor.

Bu bilgiler de ilginç ve faydalı ama benim sorumu cevaplıyor mu? Çünkü her eklediğimde diğerlerini aşağıya kaydırıyor gibi görünüyor! Yoksa bu da gerçeğin farklı olduğunu (soru içinde soru: bu nasıl olabilir ki; bir verinin niye iki adresi var ve sanki karmaşık sayılar gibi biri sanal biri gerçek! Eee peki gerçeğe ulaşabilir miyiz?) mu gösteriyor?

Alıntı (Ali Çehreli):
> ekle()'de ve başınaEkle()'de de öyle olmasını beklerim. Onlar ayrıca AĞAÇ almamalılar, üzerinde çağrıldıkları AĞAÇ nesnesini değiştirmeliler.
Bunu da anlamadım ama asıl sorundan uzaklaşmamak için sormuyorum...:)

Yakında hepsini anlayacağım...hahay (sayenizde!)

-- 
[ Bu gönderi, <http://ddili.org/forum>'dan dönüştürülmüştür. ]
February 21, 2012

Alıntı (Salih Dinçer):

>

Alıntı (Ali Çehreli):

>

ekle()'de ve başınaEkle()'de de öyle olmasını beklerim. Onlar ayrıca AĞAÇ almamalılar, üzerinde çağrıldıkları AĞAÇ nesnesini değiştirmeliler.
Bunu da anlamadım ama asıl sorundan uzaklaşmamak için sormuyorum...:)

Yakında hepsini anlayacağım...hahay (sayenizde!)

Doğru mu, yanlış mı tam olarak emin değilim ama ben anladığımı yazayım, gerekirse Ali'nin düzeltmesini severek okurum.

Sanırım Ali şöyle bişey anlatmaya çalışmış, benzetme biraz kaba olabilir.

Örneğin kendi bedenini ve bu bedeninde yer alan kolunu düşün, eğer sen su içmek istersen kolunu kullanırsın bunun etkisini bedenin görür yani su içmek için bedenini alıp başka bir kola monte etmek gibi garip bir işe girişmezsin (örneğin diyorum tabi) Burada "AĞAÇ" yapısını gövde ve ekle() metodunu kol olarak düşünürsen sanırım açıklama daha anlaşılır olacak.

Tabi ki beden ve kol örneğinde yanlışlık çok net görülmesine rağmen, kodlarla çalışırken genelde bu durum daha zor anlaşılır. Ancak Ali gibi görmeyi bilen gerçek gözler genelde bunları gayet net bir şekilde görür :)

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

February 21, 2012

Tamam, adresleri bir kenara bırakalım. Zaten çok kafa karıştırıcılar ama bu veri yapısını anlamak için şart diye düşünüyorum...:)

Çünkü nedense tüm veriyi ekrana yazdırdıktan sonra tekrar bir ekleme yapmazsam az önce çalışan satırları tekrar etmeme rağmen hiç bir şey gelmiyor. Her halde son elemanda kaldığı (null olduğu) için öyle. Bu seferde başlangıç adresinin yedeğini alıp geri yükleyim dediğimde de tek değer geliyor. Bütün bunlar Zafer'in şu sadeleştirilmiş kodunda yapmıştım: http://ddili.org/forum/post/5076

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

February 21, 2012

Alıntı (Salih Dinçer):

>

Çünkü her eklediğimde diğerlerini aşağıya kaydırıyor gibi görünüyor!

Nesnenin üyesinin adresini yazdırma işini bir kenara bırakmalısın çünkü bazen bağlı listeye eklediğin nesnenin değil, onun bir kopyasına bakıyorsun.

Alıntı:

>

bir verinin niye iki adresi var

Acaba fazla mı derin düşünüyorsun? :) Konu o kadar karışık değli. Bak şurada da aynı verinin iki adresi var:

void main()
{
   int i = 42;
   int kopyası = i;

   assert(&i != &kopyası);
}

Aynı 42 değerinin iki farklı adresi var. Yapılarda da durum aynı:

struct Y
{
   int i;
}

void main()
{
   auto y = Y();
   auto kopyası = y;

   assert(&y != &kopyası);
   assert(&(y.i) != &(kopyası.i));
}

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

February 21, 2012

Alıntı (Salih Dinçer):

>

Alıntı (Ali Çehreli):

>

ekle()'de ve başınaEkle()'de de öyle olmasını beklerim. Onlar ayrıca AĞAÇ almamalılar, üzerinde çağrıldıkları AĞAÇ nesnesini değiştirmeliler.
Bunu da anlamadım

Bu temel bir NYP kavramı. Sarma (encapsulation) ile de yakından ilgili. Üye işlevler, yapının (veya sınıfın) belirli bir nesnesi üzerinde çağrılırlar. O belirli nesne 'this' referansı ile erişilen nesnedir ama açıkça 'this' yazmaya da gerek yoktur.

Bağlı listeyi bir kenara bırakıp değer arttıran arttır() diye bir üye işlevle oynayalım:

struct Sayı
{
   int i;

   void arttır(int ek)
   {
       i += ek;
   }
}

O arttır işlevi hangi i'yi arttırıyor? Bir tür tanımladık ama tek i var. Bütün Sayı nesneleri aynı i'yi mi kullanırlar? Hayır. Hepsinin kendi i'is olur:

   auto sayı0 = Sayı(10);
   auto sayı1 = Sayı(42);

İki nesnenin farklı i'leri var. Şimdi onlar üzerinde arttır() işlevin çağırınca, arttır()'ın üzerinde çağrıldığı nesnenin değeri değişir:

   sayı0.arttır(1);
   sayı1.arttır(2);

O satırlara bakınca sayı0'ın değerinin 1, sayı1'in değerinin de 2 arttığını anlarız. NYP'ye uygun olur.

Senin bağlı listedeki ekle() işlevi ise üye işlevin üzerinde çağrılmış olduğu nesneyi değil, ayrıca parametre olarak verilen nesneyi değiştiriyordu. Bu örneğe devam edersek şununla aynı oluyordu:

struct Sayı
{
   int i;

   void arttır(int ek, Sayı * sayı)  // <-- Başka bir Sayı
   {
       sayı.i += ek;  // <-- Parametre olan Sayı'yı değiştirdik
   }
}

İşte o garip; çünkü bu nesnenin i'sini değil, parametre olarak geleni değiştirdik. Şimdi o kullanıma uyan biçimde çağıralım:

   sayı0.arttır(1, &sayı1);
   sayı1.arttır(2, &sayı0);

Hangisi 1 artar, hangisi 2 artar? NYP'ye alışmış birisi sayı0'ın 1, sayı1'in de 2 artacağını bekler. Ama bu yeni üye işlev tersini yapıyor.

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

February 22, 2012

Biraz yabancı kaynaklara bakıyorum...

Şuradaki Wikipedia maddesi ilgimi çekti: http://en.wikipedia.org/wiki/Priority_queue

Veri yapılarında çok farklı olaylar varmış. Belki de her şeyi bir veri tabanı yöneticisiyle işbirliği halinde yapmak daha mantıklı da olabilir. Ancak küçük veriler için hızlı çözümlerin tercih edildiği çok ortam var.

Bu tartışmalar zinciri için katılan ve katılmayan herkese teşekkürler. Çünkü bana çok faydası oldu ve umarım başkası içinde olur. İzleyip de cevap vermeyen arkadaşlar da katkı sağlarsa belki daha çok şey öğreniriz. Belki bu güzel forum Ali hoca ile dialog ortamına dönmez...:)

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

February 23, 2012

Hocayı biliyorum çok iyi bir kitabı vardır ama sanki çok pahalı olduğu için almamıştım. Zannedersem A'dan Z'ye (iterasyonlar dahil!) bir çok mevzu örneğin Graf Theory işlenmiş. Bir de aynı hocanın Yapay Zeka kitabı var ki kesinlikle tavsiye ederim. O da pahalı bir kitap...:)

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

February 22, 2012

Şimdi bütün bunları birleştirmek için bir algoritmalar ve veri yapıları kitabı okumanın zamanı geldi. :)

Daha bugün bizim Mengü Ceviz.net'te şöyle yazdı:

Alıntı:

>

Algoritmalar konusunda Türkçe'deki en geniş Kaynak Prof. Dr. Vasif Nabiyev'in Algoritmalar Teoriden Uygulamalara adlı kitabı , sonra Encyclopedia of Algorithms kitabı da güzel. İngilizce'niz varsa yararlı olur.

Ben kendim Robert Sedgewick'in "Algorithms in C++" kitabını okumuştum. Bayılmıştım. Aynı kitabın başka diller için olanları da var. Bilgiler aynı; yalnızca küçük kod örnekleri farklı.

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

« First   ‹ Prev
1 2