Forum: Ders Arası RSS
Yapı içinde bağlı liste oluşturmak...
Linked Lists
Sayfa:  1  2  sonraki 
Avatar
Salih Dinçer #1
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Konu adı: Yapı içinde bağlı liste oluşturmak...
Merhaba,

D.ersahane'nin ilgili dersindeki örnek programı aşağıya (yatık yazı benim eklememdir) alıntılıyorum:

(Bu arada unutmadan küçük bir öneri; dersin bölümlerine bağlantı|anchor tanımlayabilsek ne iyi olurdu...)
Göstergeler Dersi:
başınaEkle işlevinde yer alan ilk satırda sağ tarafta dinamik bir Düğüm nesnesi oluşturuluyor. Bu yeni nesne kurulurken, sonraki üyesi olarak listenin şu andaki başı kullanılıyor. Listenin yeni başı olarak da bu yeni düğümün adresi kullanılınca, listenin başına eleman eklenmiş oluyor.

Bu küçük veri yapısını deneyen küçük bir program:
struct Düğüm
{
    int eleman;
    Düğüm * sonraki;
 
    this(int eleman, Düğüm * sonraki)
    {
        this.eleman = eleman;
        this.sonraki = sonraki;
    }
 
    string toString() const
    {
        string sonuç = to!string(eleman);
 
        if (sonraki) {
            sonuç ~= " -> " ~ to!string(*sonraki);
        }
 
        return sonuç;
    }
}
 
struct Liste
{
    Düğüm * baş;
 
    void başınaEkle(int eleman)
    {
        baş = new Düğüm(eleman, baş);
    }
 
    string toString() const
    {
        return format("(%s)", baş ? to!string(*baş) : "");
    }
}
 
void main()
{
    Liste sayılar;
 
    writeln("önce : ", sayılar);
 
    foreach (sayı; 0 .. 10) {
        sayılar.başınaEkle(sayı);
    }
 
    writeln("sonra: ", sayılar);
}
Çıktısı:
önce : ()
sonra: (9 -> 8 -> 7 -> 6 -> 5 -> 4 -> 3 -> 2 -> 1 -> 0)
Yukarıdaki örnekteki Düğüm ve Liste yapılarını anlamaya çalışıyorum da veri, Düğüm yapısı içinde tutulduğuna göre Liste'nin tam olarak görevi nedir; ya da Liste aslında düğümlerin kendisi olabilir mi? Gerçi hayatta bir çok şey tersine işler (burada verilerin ters belleğe yerleşmesi gibi), belki de burada da bir ters mantık olabilir ama anlamakta zorlanıyorum... :rolleyes:

Yardımcı olursanız sevinirim, teşekkürler...
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
Avatar
Salih Dinçer #2
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Tekrar Merhaba...:)

Belleğe yerleşim bölgelerini görebilmek için main()'i aşağıdaki gibi ve bir de Düğüm içinde tek satırı değiştirdim. Sonuçta altındaki gibi bir çıktı aldım. Görünüşe göre her düğüm arasında epey bir boşluk (ubyte da denedim aynı!) varken; yapıların ilk elemanları ile yapıların adresleri aynıymış. Ayrıca  *sonraki, Düğüm'ün başka bir kopyası (göstergesi) ama adresi farklı...

Son olarak ne hikmetse adresler hep geriye doğru gidiyor...:)
/*
 listeyeEkle.d (19.02.2012)
*/
import std.array, std.conv, std.stdio, std.string, std.random;
 
struct Düğüm {
// ...
string toString() const {
        string sonuç = format("%d\t@%X\n", eleman, &eleman);
// ...
 
void main() {
    Düğüm say;
    Liste sayılar;    
    
    writeln("Liste\t@", &sayılar, "\t.baş      @", &sayılar.baş);
    writeln("Düğüm\t@", &say, "\t.eleman   @", &say.eleman, "\t.sonraki  @", &say.sonraki);
 
    foreach (sayı; 0 .. 10) sayılar.başınaEkle(sayı);
 
    writeln(sayılar);
}
Çıktısı:
salih@DB-N150-N210-N220:~/d.ders$ dmd listeyeEkle.d
salih@DB-N150-N210-N220:~/d.ders$ ./listeyeEkle
Liste    @BFA99BD4    .baş      @BFA99BD4
Düğüm    @BFA99BCC    .eleman   @BFA99BCC    .sonraki  @BFA99BD0
 -> 9    @BFA999F0
 -> 8    @BFA99950
 -> 7    @BFA998B0
 -> 6    @BFA99810
 -> 5    @BFA99770
 -> 4    @BFA996D0
 -> 3    @BFA99630
 -> 2    @BFA99590
 -> 1    @BFA994F0
 -> 0    @BFA99450
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
Bu mesaj Salih Dinçer tarafından değiştirildi; zaman: 2012-02-19, 06:05.
acehreli (Moderatör) #3
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Yanıtlanan mesaj #1
Salih Dinçer:
veri, Düğüm yapısı içinde tutulduğuna göre Liste'nin tam olarak görevi nedir

Öncelikle hayatımda yalnızca bir kaç kere bağlı liste yazmış olduğumu hatırlatayım. :) C++ ve D gibi diller elle yazılmalarını gerektirmeyecek kadar güçlüler. C++'ta std::list'i kullanırdım, D'de de std.container.SList'i...

Ben, düğüm kavramını bağlı listenin yapı taşı olarak ayrıca tanımladım: Her düğüm tek eleman barındırıyor ve bir sonraki düğümü gösteriyor.

Liste ise hangi düğümden başlandığını tutan tek göstergelik bir yapı. Daha kapsamlı bir liste olduğunda sonuncu elemanı da bu dış yapı gösterebilir.

Ayrıca toString() işlevleri de farklı: Düğümler kendi elemanlarını yazdırıyorlar ve yazdırma işlemini sonraki düğüme havale ediyorlar. Burada özyinelemeli bir durum var. Liste düzeyinde ise özyineleme yok: baştaki düğümün string olarak ifadesini elde ediyor ve etrafına parantez yazıyor.

O yüzden düğümüm ve listenin farklı düzeylerde kavramlar olduklarını düşündüm.

Yalnız bir hata yaptım ve hoş durduğu için başınaEkle() işlevinin içini tek satır olarak yazdım:

    void başınaEkle(int eleman)
    {
        baş = new Düğüm(eleman, baş);
    }

Şöyle daha açıklayıcı olabilirdi:

    void başınaEkle(int eleman)
    {
        Düğüm * yeniDüğüm = new Düğüm(eleman, baş);
        baş = yeniDüğüm;
    }

Gerçi hayatta bir çok şey tersine işler (burada verilerin ters belleğe yerleşmesi gibi)

Burada bağlı listenin ters oluşmasının tek nedeni, Liste'nin basitliği. Yoksa 'son' diye bir gösterge de barındırabilir ve yeni düğümü ona bağlayabilirdir. Veya hızdan ödün vererek baştan başlayarak sonuncu düğümü bulurdu ve oraya ekleyebilirdi.

Ali
acehreli (Moderatör) #4
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Yanıtlanan mesaj #2
Salih Dinçer:
Görünüşe göre her düğüm arasında epey bir boşluk (ubyte da denedim aynı!) varken;

O adresler bizim dışımızdaki düzenekler tarafından veriliyorlar. Kendi bildikleri iş. Adresleri gözlemlediğimizde artan yönde, azalan yönde, veya karışık yönde görebiliriz. Belleğin o anda neresinin boş olduğuna bağlıdır.

yapıların ilk elemanları ile yapıların adresleri aynıymış.

Aynen öyle. C'de de öyledir. D yapıları ile C yapıları bire bir örtüşürler. (C++ yapıları ise ancak POD (plain old data) şartını sağlarlarsa öyledirler.)

Ayrıca  *sonraki, Düğüm'ün başka bir kopyası (göstergesi) ama adresi farklı...

'sonraki' bir gösterge olduğuna göre '*sonraki' onun gösterdiği değişken oluyor. Yani başka bir Düğüm.

Ali
acehreli (Moderatör) #5
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Görsel olarak deniyorum. Elimizde iki elemanlı bir liste bulunsun. new ile oluşturulmuş olan düğümlerin bellekte ilgisiz yerlerde olabildiklerini gösterebilmek için karışık olarak çiziyorum:


              ..............
             | eleman: 100  |
             | sonraki:null |
              ..............
                   ^
Liste:             |
 .....             |
| baş -----        |
 .....     |       |
           |        ---------------------
           |                             |
           |              ...........    |
            ------------>| eleman: 7 |   |
                         | sonraki ------
                          ...........


Listenin 'baş' üyesi baştaki elemanı gösteriyor. Onun değeri 7. O da bir sonraki elemanı gösteriyor. Onun değeri 100. Artık ondan sonra düğüm gösterilmiyor çünkü onun 'sondaki' üyesinin değeri null.

Şimdi şu işlevin nasıl işlediğine bakalım:

    void başınaEkle(int eleman)
    {
        Düğüm * yeniDüğüm = new Düğüm(eleman, baş);
        baş = yeniDüğüm;
    }

Eleman değeri 42 olduğunda o birinci satır işletildiğinde durum şunun gibidir:


              ..............
             | eleman: 100  |
             | sonraki:null |
              ..............
                   ^
Liste:             |
 .....             |
| baş -----        |
 .....     |       |
           |        ---------------------
           |                             |
           |              ...........    |
            ------------>| eleman: 7 |   |
                         | sonraki ------
                          ...........
                               ^
                               |
                               |
                                ..........
                                          |
                                          |
                          ............    |
yeniDüğüm   ------------>| eleman: 42 |   |
                         | sonraki -------
                          ...........


Yeni düğüm oluşturulurken onun sonraki üyesinin değeri olarak 'baş'ın değeri kullanıldığı için şimdi hem 'baş' hem de 'yeniDüğüm.sonraki' aynı düğümü gösteriyorlar.

Ondan sonra kodun ikinci satırına geçiyoruz ve 'baş'ın 'yeniDüğüm'ü göstermesini sağlıyoruz. Şimdi durum şu:


              ..............
             | eleman: 100  |
             | sonraki:null |
              ..............
                   ^
Liste:             |
 .....             |
| baş -----        |
 .....     |       |
           |        ---------------------
           |                             |
           |              ...........    |
           |             | eleman: 7 |   |
           |             | sonraki ------
           |              ...........
           |                   ^
            ---------------    |
                           |   |
                           |    ----------
                           |              |
                           v              |
                          ............    |
yeniDüğüm   ------------>| eleman: 42 |   |
                         | sonraki -------
                          ...........


Evet şu anda yeni eklenen 42 değeril düğümü gösteren iki gösterge var: baş ve yeniDüğüm. Ama olsun, bu işlevden çıkıldığında yeniDüğüm isimli gösterge uçup gidecek ve geriye şu kalacak:


              ..............
             | eleman: 100  |
             | sonraki:null |
              ..............
                   ^
Liste:             |
 .....             |
| baş -----        |
 .....     |       |
           |        ---------------------
           |                             |
           |              ...........    |
           |             | eleman: 7 |   |
           |             | sonraki ------
           |              ...........
           |                   ^
            ---------------    |
                           |   |
                           |    ----------
                           |              |
                           v              |
                          ............    |
                         | eleman: 42 |   |
                         | sonraki -------
                          ...........


İşte başına işleme olayı gerçekleşmiş oldu.

Ali
Avatar
Salih Dinçer #6
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Yanıtlanan mesaj #4
Teşekkürler...

Bellek kontrolünü hiç bilmiyorum. Neyse ki D, bunu bizim için yapıyor. Yoksa malloc()'lar ile kafayı yerdim; eminim...:)

Bu bağlı liste hakkında D'de çok fazla örnek bulamadığım için C örneklerine bakıyorum. Şurada çok güzel bilgiler buldum:

[Resim: http://ddili.org/forum/unb_lib/designs/modern/img/arrow_right.png] http://cslibrary.stanford.edu/103/LinkedListBasics.pdf (46 Kb.)

Ancak hala araya ekleme, sıralama ve silme olaylarını beceremedim ama yaklaştım. Mesele C'de YAPI şöyle oluşturuluyormuş:
struct node* Build() {
    struct node* head = NULL;
 
    head = malloc(sizeof(struct node)); // allocate 3 nodes in the heap
    head->data = 1; // setup first node
    head->next = second; // note: pointer assignment rule
 
    // At this point, the linked list referenced by "head" matches the list in the drawing.
 
    return head;
}
Neyse, konumuzda, forumuzda D... Yani önemli olan D ile yapabilmek. İlk olarak şöyle bir şeyler yaptım ama çok eksiğim var. Devam etmeden önce hatalarım var mı öğrenmek isterim?
/*
 listeyeEkle.d (19.02.2012)
*/
import std.array, std.conv, std.stdio, std.string, std.random;
 
struct AĞAÇ {
    ubyte yaprak;
    AĞAÇ* sonrakiDal;
 
    this(ubyte yaprak, AĞAÇ* sonrakiDal) {
        this.yaprak = yaprak;
        this.sonrakiDal = sonrakiDal;
    }
    void ekle(ubyte 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Ç* tmp, soy = new AĞAÇ(0, null);
 
    ubyte [] s = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ];
    auto r = Random(unpredictableSeed);
    
    tmp = soy;
    foreach(e; randomCover(s, r))
    {
        soy.ekle(e, tmp);
    }
    
    writeln("AĞAÇdakiler~~~~v\n", to!string(*soy));
}
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
Bu mesaj 2 defa değişti; son değiştiren: Salih Dinçer; zaman: 2012-02-19, 11:25.
Avatar
Salih Dinçer #7
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Yanıtlanan mesaj #5
acehreli:
Görsel olarak deniyorum. Elimizde iki elemanlı bir liste bulunsun. new ile oluşturulmuş olan düğümlerin bellekte ilgisiz yerlerde olabildiklerini gösterebilmek için karışık olarak çiziyorum:

              ..............
             | eleman: 100  |
             | sonraki:null |
              ..............
                   ^
Liste:             |
 .....             |
| baş -----        |
 .....     |       |
           |        ---------------------
           |                             |
           |              ...........    |
            ------------>| eleman: 7 |   |
                         | sonraki ------
                          ...........

Bu çok çok güzel bir gösterim şekli, elinize sağlık. Şimdi ayrıntısı ile inceleceğim. Ben yukarıdaki iletimi yazarken aynı konudaymışız...:)

O yüzden gönderdikten sonra gördüm. Bu arada yukarıdaki kodların içinde diğer konudan olan işlevlerde var. Bilmiyorum ikisini karşılaştırmaya orada mı devam etsek?

Sevgiler, saygılar...
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
acehreli (Moderatör) #8
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Yanıtlanan mesaj #6
Salih Dinçer:
Ancak hala araya ekleme, sıralama ve silme olaylarını beceremedim ama yaklaştım.

Çok normal. ;) Baştan çok zorlayan ama birden anlaşılan bir konudur.

Mesele C'de YAPI şöyle oluşturuluyormuş:
struct node* Build() {
    struct node* head = NULL;
 
    head = malloc(sizeof(struct node)); // allocate 3 nodes in the heap
    head->data = 1; // setup first node
    head->next = second; // note: pointer assignment rule
 
    // At this point, the linked list referenced by "head" matches the list in the drawing.
 
    return head;
}

C++ forumlarında hep tekrarlarım: C++'ın new'ü, C'nin "malloc() + üye ilkleme" işleminin eşdeğeridir. Yani bellekten yer ayırma ve nesne kurma.

Neyse ki D'de kurucu işlev kavramı hem de otomatik olarak bulunduğundan şu D işlevi yukarıdaki C işlevinin eşdeğeri oluyor:

struct node* Build() {
    node* head;                    // D'de zaten null olarak ilklenir
 
    head = new node(1, second);    // aradaki üç satırın eşdeğeri
 
    return head;
}

Değişkenlerin tanımlandıkları satırda ilklenmeleri C'de haklı nedenlerle yaygın değildir. D'de şu daha iyi:

struct node* Build() {
    node* head = new node(1, second);
 
    return head;
}

Ama bazen kodun anlaşılmasının engellenmediği düşünüldüğünde daha da kısa olarak:

struct node* Build() {
    return new node(1, second);
}

C'de nasıl her işlem teker teker yapılmak zorundaydı ama D'de nasıl üst düzey bir kavram olarak açıkladık: "değeri 1 olan ve second'ı gösteren bir node oluştur ve döndür."

Devam etmeden önce hatalarım var mı öğrenmek isterim?

YAPI güzel bir isim değil. ;)

listeyeEkle()'nin görevini güzelce oturtmak gerek. Neden YAPI'nın bir üye işlevi? Üye işlev olduğunda şu anda üzerinde işlediği nesneye bir etkisinin olmasını bekleyebiliriz. Örneğin veri ve sonraki üyelerini değiştirmesini bekleyebiliriz.

Ama anladığım kadarıyla 'bağı' parametresinin sonrasına yeni bir düğüm ekliyor. Burada bir soru: ya 'bağı'nın sonrasında zaten bir düğüm varsa? O zaman o bağlantıyı kopartmış oluruz.

Yanlış demiyorum. Yalnızca kafamda böyle sorular oluştu. Ama sonuçta bağlı liste bir kaç göstergeye başka düğüm göstertme üzerine kurulu olan basit bir olay. Kağıt üzerinde düşünmek de çok yararlı oluyor. Devam... :)

Ali
Avatar
Salih Dinçer #9
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Ali Çehreli:
Salih Dinçer:
Devam etmeden önce hatalarım var mı öğrenmek isterim?

YAPI güzel bir isim değil. ;)

listeyeEkle()'nin görevini güzelce oturtmak gerek. Neden YAPI'nın bir üye işlevi? Üye işlev olduğunda şu anda üzerinde işlediği nesneye bir etkisinin olmasını bekleyebiliriz. Örneğin veri ve sonraki üyelerini değiştirmesini bekleyebiliriz.

Ama anladığım kadarıyla 'bağı' parametresinin sonrasına yeni bir düğüm ekliyor. Burada bir soru: ya 'bağı'nın sonrasında zaten bir düğüm varsa? O zaman o bağlantıyı kopartmış oluruz.

Aklıma ilk anda fazla bir şey gelmediği için YAPI kullandım. Karışıklık olmasın diye sonradan iletiyi değiştirmeme gibi bir prensibimiz var; biliyorum ama sadece kodun gereksiz yerlerini çıkarıp aklıma gelen şeyi düzelttim:
Salih Dinçer:
void main (){
    AĞAÇ* tmp, soy = new AĞAÇ(0, null);
 
    ubyte [] s = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ];
    auto r = Random(unpredictableSeed);
    
    tmp = soy;
    foreach(e; randomCover(s, r))
    {
        soy.ekle(e, tmp);
    }
    
    writeln("AĞAÇdakiler~~~~v\n", to!string(*soy));}
Bilmiyorum, mümkün mü? Yani yaşam ağacı (Şecere) bana açıklamak için güzel göründü. Gerçi yaprak yerine aile kullanmak daha akıllıca olabilir. Standartların aksine AĞAÇ'ı özellikle büyük yazıyorum çünkü kod aralarında belirgin görünmesi iyi oluyor. Bağ yerine de yaprakların boğumları, ok çizgileri de dal (kodda sonrakiDal) şeklinde düzenledim. Şimdi güzel oldu mu?

Devam etmeden önce bugün öğrendiklerimi hazmedeyim. Genelde uzanıp sabaha kadar (bazen rüyalarda!) düşünüyorum ve uyandığımda deli gibi kod yazmak istiyorum...:)

Dip Not: Gerçek bir şecere için, sanırım daha çok elemanlı bir yapı kurmak gerekiyor. Biraz düşünmeliyim...

Sevgiler, saygılar...
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
acehreli (Moderatör) #10
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Salih Dinçer:
Aklıma ilk anda fazla bir şey gelmediği için YAPI kullandım.

Tabii ki. :) İsimler çok önemli. Güzel isim veremediğimiz zaman tasarımda sorun var demektir. Örneğin birden fazla kavramı temsil etmeye çalışıyoruzdur veya fazla sorumluluk vermişizdir, vs.

yaşam ağacı (Şecere) bana açıklamak için güzel göründü.

Bir şanssızlık, en yaygın üçüncü veri yapısının ismini seçmişsin: dizi, liste, ağaç. ;) (Yaygınlık sıralarını uyduruyorum tabii ki. :-p) Bağlı listeye ağaç demek karışıklık yaratır. İngilizce isimleri:

  • array

  • linked list

  • tree (daha çok 'binary tree')

D'nin eşleme tabloları olan 'hash table' da başlıca veri yapılarından bir diğeridir.

sabaha kadar (bazen rüyalarda!) düşünüyorum

Ne güzel! :) Uykunun o günkü problemlerin irdelenmesi ve yeni çözümler aranması ile ilgili olduğu biliniyor.

Ali
Avatar
Salih Dinçer #11
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Ayrıca yeni fikirlerin... :rolleyes:

Bugün (bu yeni haftanın ilk gününün) verimli geçeceğini düşünüyorum. Bağlı listeleri tuttum ve kopartacağım inşaallah...:)

Belki ters bir şeyler yapıyorum diye bellekteki değerlerin kaymasını yukarıdaki (D.ershane'deki) kodlar ile de denedim:
    writeln("Liste\t@", &sayılar, "\t.baş      @", &sayılar.baş);
    writeln("Düğüm\t@", &say, "\t.eleman   @", &say.eleman, "\t.sonraki  @", &say.sonraki);
    sayılar.başınaEkle(10);
    writeln(sayılar);
Yine aynı şey oluyor ki başınaEkle() işlevinden (ilk kurulum dışında) uzak durmamız gerekli diye düşünüyorum. Yoksa yavaş olacağı aşikar öyle değil mi? Çıktısı ise şöyle:

(9    @BFB49BF0
 -> 8    @BFB49B50
 -> 7    @BFB49AB0
 -> 6    @BFB49A10
 -> 5    @BFB49970
 -> 4    @BFB498D0
 -> 3    @BFB49830
 -> 2    @BFB49790
 -> 1    @BFB496F0
 -> 0    @BFB49650
)
Liste    @BFB49DD4    .baş      @BFB49DD4
Düğüm    @BFB49DCC    .eleman   @BFB49DCC    .sonraki  @BFB49DD0
(10    @BFB49BF0
 -> 9    @BFB49B50
 -> 8    @BFB49AB0
 -> 7    @BFB49A10
 -> 6    @BFB49970
 -> 5    @BFB498D0
 -> 4    @BFB49830
 -> 3    @BFB49790
 -> 2    @BFB496F0
 -> 1    @BFB49650
 -> 0    @BFB495B0
)
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
zafer #12
Üye Tem 2009 tarihinden beri · 700 mesaj · Konum: Ankara
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Yanıtlanan mesaj #10
import std.stdio;
 
struct Dugum
{
    int eleman;
    Dugum * sonraki;
 
    this(int eleman, Dugum * sonraki)
    {
        this.eleman = eleman;
        this.sonraki = sonraki;
    }
};
 
void main()
{
    Dugum * basDugum;
    Dugum * yeniDugum;
 
    basDugum = new Dugum(1, basDugum);
 
    yeniDugum = new Dugum(2, basDugum);
    basDugum = yeniDugum;
 
    yeniDugum = new Dugum(3, basDugum);
    basDugum = yeniDugum;
 
 
    while (basDugum != null)
    {
        writefln("-> %s", basDugum.eleman);
        basDugum = basDugum.sonraki;
    }
}

Umarım yardımcı olur. Ali'nin örneğini mümkün olduğunca küçültmeye çalıştım. Şu adreste (http://www.zafercelenk.net/post/2009/08/21/Bagl%C4%B1-List…) benim yazdığım küçük bir yazı ve kodlar var belki fikir verebilir diye ekliyorum.

Diğer taraftan Ali'ninde yazdığı gibi bağlı listeyi mutlaka kağıt üzerinde çalış, hem kendine dönüşlü yapılan yüzünden, hemde göstericilerin adresleri üzerinden takaslar yapıldığı için kodlarla bu yapıyı anlamak zor oluyor. Ama kağıt ve kalemle en fazla 10 dakikada kavrayabileceğin basit bir olay  ;-)

Bu arada şöyle bir kodun D karşılığı ne olabilir?
basDugum = (struct dugum *) malloc(sizeof(struct dugum));
https://github.com/zafer06 - depo
Avatar
Salih Dinçer #13
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Teşekküler Zafer, inceleyeceğim...

zafer:
Bu arada şöyle bir kodun D karşılığı ne olabilir?
basDugum = (struct dugum *) malloc(sizeof(struct dugum));
Bundan sanırım, Ali hoca bahsetmişti ve her şeyi new(), dolayısıyla çöp toplayıcı üstleniyormuş. Bu durumda karşılığı şöyle olsa gerek:
dugum* basdugum;
basDugum = cast(dugum*) new dugum(null);
Tabi cast() gereksiz duruyor, D'nin gözünü seveyim bea...:)

Bu arada makaleni okudum ve kutular ile (adresleri ile birlikte) ifade edilen görüntü çok hoşuma gitti. İşte beneklerin (pixel) gücü ama karakterler ile yapılan da çok nostaljik göründüğünü itiraf etmeliyim, yani o da hoş.

Bir kaç deneme yaptım, aslında şu adres olayını kafaya taktım. O yüzden C'ye dönüp çöp toplayıcısı olmayan bir derleyiciye geçmeyi düşünüyorum. Çünkü son aldığım sonuç beni bir kere daha şaşırttı. Şöyle ki; Zafer'in makalesindeki kutularda yer alan adreslerden, acaba bir sonrakinin adresini ekrana yazdırıp yazdıramayacağımı merak ettim. Gel gör ki belleğin çok farlı bölgelerinden şeyler ekrana gelince vaz geçtim. Bakınız:

AĞAÇdakiler~~~~~v
0    @BFE5FF04
1    @BFE5FE64
2    @BFE5FDC4
3    @BFE5FD24
AĞAÇ    @BFE5FF8C    .yaprak   @B7673FF0    .sonrakiDal  @B7673FF4
AĞAÇ     B7673FF0    .yaprak    0           .sonrakiDal   B7673FB0


Son iki satırın kodu ise şu:
writeln("AĞAÇ\t@", &soy, "\t.yaprak   @", &soy.yaprak, "\t.sonrakiDal  @", &soy.sonrakiDal);
    writeln("AĞAÇ\t ", soy, "\t.yaprak    ", soy.yaprak, "\t\t.sonrakiDal   ", soy.sonrakiDal);
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
Bu mesaj Salih Dinçer tarafından değiştirildi; zaman: 2012-02-20, 04:03.
acehreli (Moderatör) #14
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Yanıtlanan mesaj #12
zafer:
Şu adreste (http://www.zafercelenk.net/post/2009/08/21/Bagl%C4%B1-List…) benim yazdığım küçük bir yazı ve kodlar var belki fikir verebilir diye ekliyorum.

Güzelmiş! :)

Bu arada şöyle bir kodun D karşılığı ne olabilir?
basDugum = (struct dugum *) malloc(sizeof(struct dugum));

Salih'in gösterdiği gibi new() olur ama tam karşılığı olmuyor tabii ki çünkü malloc() ilklenmemiş çiğ bellek ayırır. new() ise ayırdığı bellek üzerinde kullanıma hazır bir nesne oluşturur.

D'de de boş bellek ayrılabiliyor ama önemli sakıncaları ve kuralları var. Benim bildiklerim şurada yazılı:

  http://ddili.org/ders/d/bellek_yonetimi.html

Özellikle "Bellekten yer ayırmak" başlığı altında C'nin malloc()'unun kullanımı bile var.

Ali
zafer #15
Üye Tem 2009 tarihinden beri · 700 mesaj · Konum: Ankara
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
acehreli:
D'de de boş bellek ayrılabiliyor ama önemli sakıncaları ve kuralları var. Benim bildiklerim şurada yazılı:

  http://ddili.org/ders/d/bellek_yonetimi.html

Özellikle "Bellekten yer ayırmak" başlığı altında C'nin malloc()'unun kullanımı bile var.

D dilinde bellek ayırma işlemini bir yerde gördüğüm aklımdaydı ama nerede olduğunu bir türlü hatırlayamamıştım :) Nerede gördüğümü şimdi anladım :)
https://github.com/zafer06 - depo
Doğrulama Kodu: VeriCode Lütfen resimde gördüğünüz doğrulama kodunu girin:
İfadeler: :-) ;-) :-D :-p :blush: :cool: :rolleyes: :huh: :-/ <_< :-( :'( :#: :scared: 8-( :nuts: :-O
Özel Karakterler:
Sayfa:  1  2  sonraki 
Forum: Ders Arası RSS
Bağlı değilsiniz. · Şifremi unuttum · ÜYELİK
This board is powered by the Unclassified NewsBoard software, 20100516-dev, © 2003-10 by Yves Goergen
Şu an: 2017-11-22, 02:59:13 (UTC -08:00)