Forum: Ders Arası RSS
Yapı içinde bağlı liste oluşturmak...
Linked Lists
Sayfa:  önceki  1  2 
Avatar
Salih Dinçer #16
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Yanıtlanan mesaj ID 5074
Peki D dilinde listelere ekleme yapıp çıkarmak için method'lar yok mu? C#'da inanılmaz çok örnek ile karşılaştım. Gerçi bir sürü ekleme ve çıkarma komutuyla işi iyice karıştırmışlar...:)

Kolaylıkları da yok değil hani. Mesela listeyi şöyle tek satırda, verileri ile birlikte kurabiliyormuşuz:
LinkedList<int> primes = new LinkedList<int>(new int[] { 3, 5, 7, 11, 15, 17 });
 
Çıkarmaya iki method var ki ilki herkesin aklına gelen: primes.Remove(15); şeklinde...
Diğer yöntem primes.RemoveAt(1) ki bu ikinci elemanı çıkar demek. (-bknz. www.dotnetperls.com/list-remove)

Eklerken, teker teker (sadece Add ile) sıralı bir şekilde, başa ve sona olmak üzere üç etti. Bir de bulduktan sonra AddAfter() toplam da dört tane var:
primes.Add(2);
primes.Add(3);
primes.Add(5);
: : :
 
Sık kullanılanlar ise şunlar:
 
primes.AddFirst(2);
primes.AddLast(19);
 
İçlerinden birini arayacağımızda biraz uzun, LinkedListNode<int> node = primes.Find(11); şeklinde.
Hemen dördüncü ekleme komutuyla biraz işi kolaylaştırmışlar:
primes.AddAfter(node, 13);
Böylece elde ettiğimiz düğümü kullanarak araya ekliyor. Gerçi bunların temeli iki üç komut çünkü bir insert (node, item) komutu var; herhalde eklemelerin temeli budur. Ama gel gelelim ben overload olduğundan çalıştıramadım... :blush:

Sanırım boş düğüm olması gerekiyor ve oraya giriyor ya anlamadım. Neyse sonuçta biz D'yi konuşuyoruz ama bunları yaparsak 10 numara olacak.

Başarılar...
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
Bu mesaj 3 defa değişti; son değiştiren: Salih Dinçer; zaman: 2012-02-21, 13:27.
acehreli (Moderatör) #17
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ı
D'de şimdilik tek-bağlı liste olarak SList var:

  http://dlang.org/phobos/std_container.html#SList

En yakın karşılığı şu program olabilir:

import std.stdio;
import std.container;
 
void main()
{
    auto primes = new SList!int(1, 2, 3, 4, 5);
 
    primes.removeFront();
 
    primes.insert(10);
    primes.insert(11);
    primes.insertFront(12);
    primes.insertAfter(primes.opSlice(), 13);
 
    writeln(primes.opSlice());
}

[12, 11, 10, 2, 3, 4, 5, 13]

Belirli bir konumdaki elemanı çıkartma işlemi yok. (Zaten bağlı listeye uygun bir işlem değil.) find() gibi işlevleri de topluluklar üzerinde değil, algoritmalar olarak isteriz. Daha kullanışlıdır. D'de şöyle:

import std.algorithm;
// ...
    writeln(find(primes.opSlice(), 4));

Çıktısı:

[4, 5, 13]

Çünkü find(), aralığın bulduğu noktadan sonrasını yine bir aralık olarak verir. Bulunan elemanı kullanmak istediğimizde sonuç.front deriz.

Evet, opSlice() çağrısının gerekmesi çok saçma. Kısaca primes[] yazabilmeliydik. std.container'ı iyi bilmiyorum; şimdilik daha fazla kurcalamayacağım. :)

Ali
Avatar
Salih Dinçer #18
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Ali Çehreli:
D'de şimdilik tek-bağlı liste olarak SList var:

  http://dlang.org/phobos/std_container.html#SList
Vaoov...:)

Bunu öğrendiğim çok çok iyi oldu, teşekkürler...

Hemen inceliyorum hatta dayanamadım iletiyi okurken kodlarına baktım da yapıyı şu şekilde oluşturmuşlar:
struct SList(T) {
    private struct Node {
        T _payload;
        Node * _next;
        this(T a, Node* b) { _payload = a; _next = b; }
    }
    private Node * _root;
 
    private static Node * findLastNode(Node * n) {
        auto ahead = n._next;
        while (ahead) {
            n = ahead;
            ahead = n._next;
        }
        return n;
    }
: : :
Devamı... (satır 852)
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-22, 01:47.
Avatar
Salih Dinçer #19
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Merhaba,

Bugün, geçen hafta sonundan beri (sizler sayesinde) öğrendiğim bağlı liste (aslında 1978'de C'nin 2. sürümüne eklenen struct kavramının birbirlerine bağlı haliymiş: Linked List) olayını pekiştirmeye çalışıyorum...

Zafer'in, önceki sayfada yer alan temiz çözümü (clear~simple~solution) beni bir adım daha ileriye götürdü. Kendisine özellikle teşekkür ederim. Bu konuları araştırdıkça, aslında 1955'e değil benim ana karnında olduğum (1978-1979) zamana denk geldiğini öğrendim. Bu da benimle yaşıt olması anlamına geliyor ki manevi açıdan adeta gazlıyor! Düşünsenize, 30'lu yaşlarımdayım ve henüz yeni öğreniyorum: aaa çok büyük ayıp!...:)

Şaka bir yana, sormak değil öğrenmemek ayıpmış. Ancak şimdi tek bir soru dışında (-bknz. sondaki yıldızlı parantez) sorular ile daha çok başınızı şişirmek istemiyorum. Adım adım, öğrendiklerimi pekiştirmek için yaptığım son denemeleri aşağıda izleniminize sunmalıyım:

- İlk olarak anlayışı kolaylaştırmak için herkesin bildiği atom modelini temel aldım. Her şeyi en basit şekilde anlamam gerektiği için yapıyı da olabildiğince basit (sadece 3 satır!) oluşturdum:
/*
 atom.d (23.02.2012)
*/
import std.stdio;
 
struct Atom {
    Atom* element;          // Eğer adres değeri F70 ile bitiyorsa,
    ubyte proton;           // 2. eleman türden bağımsız F74 oluyor
 
    this(Atom* a, ubyte b) { element = a, proton = b; }
}
 
void main () {
    Atom* baştaki, sonraki = new Atom(null, 1);    // Hidrojen (en basit element!)
    // Yukarıda, kurulum ve ilk değerin (düğümün~node) eşitlenmesi yapılmaktadır,
    // sonraki'den kasıt, etkin olan değer(ler)i yani düğümü ifade eder...
 
    foreach(ubyte atomNumarası; 2..4) {
        baştaki = new Atom(sonraki, atomNumarası);
        sonraki = baştaki;
    } do {
        writeln(&sonraki.proton, " -> ", sonraki.proton,
                                 "@", &sonraki.element);
        sonraki = sonraki.element;
    } while(sonraki != null);
}
Çıktısı:
B7781F74 -> 3@B7781F70
B7781F84 -> 2@B7781F80
B7781F94 -> 1@B7781F90


2. Fakat teknik nedenlerden dolayı veri, tersten (-bknz. yukarıdaki çıktı) birbirlerine bağlanıyordu. Hem bunu düzeltmek, hem de main() içindeki kodlamayı basitleştirmek için yapıyı şöyle oluşturabiliriz:
struct Atom {
    Atom* element;          // Eğer adres değeri F70 ile bitiyorsa,
    ubyte proton;           // 2. eleman türden bağımsız F74 oluyor
 
    this(Atom* a, ubyte b) {
        this.element = a;
        this.proton = b;
    }
 
    void atomuEkle(ref Atom* sonraki, ubyte değeri) {
        auto ekle = new Atom(null, değeri);
        sonraki.element = ekle;
        sonraki = ekle;
    }
 
    string toString() const {
        string tamamı = format("%X -> %d", &proton, proton);
        if (element) tamamı ~= "\n" ~ to!string(*element);
        
        return tamamı;
    }
}
Satır sayısı arttığı için her şeyi yaydım tabi...:)

Özellikle, this{} kümesi içindeki özdeğişkenlerin başına tekrar this ifadesi kullanmak gerekmediğini bildiğim halde, bunun da olabileceğini göstermek için ifade etmekten kaçınmadım. Aslında satırları katık etmeyi (idareli kullanmayı) severim; böylece tek sayfada görüntüleyebileceğim satır sayısı fazla olduğundan, hakimiyeti (bu bana özel ve standartların dışında!) arttırabiliyorum.

Artık, birini (*) saymazsak sadece iki satır ile sonucu düzgün bir şekilde yansıtabiliyoruz:
import std.stdio, std.conv, std.string;   // 2 sınıf daha eklemeliydik! 
 
// main();
: : :
 
    foreach(ubyte atomNumarası; 2..4) sonraki.atomuEkle(baştaki, atomNumarası);
    writeln(to!string(*sonraki));
}
Çıktısı:
BFC4F774 -> 1@BFC4F770
BFC4F6D4 -> 2@BFC4F6D0
BFC4F634 -> 3@BFC4F630


(*) Eğer foreach() önüne yapının kopyasını birbirine eşitlemezseniz (baştaki = sonraki;) çalışma zamanı hatası verecektir!

Neden?
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-23, 11:38.
Avatar
Salih Dinçer #20
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Konu adı: Erken gelen cevap...:)
Ali Hocam, geçen hafta verdiğin aşağıdaki cevabı yeni gördüm...

Bu olsa olsa geleceğe gönderilen cevap olur...:-D

Ali Çehreli on 2012-02-19, 09:02:
    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.
Tek farkı tersten eklemesi! Bu kodu, şimdi, şu şekilde denedim:
// struct Atom {}
    void başınaEkle(ubyte değeri) {
        Atom* yenibirAtom = new Atom(element, değeri);
        element = yenibirAtom;
    }
// main ()
    //baştaki = sonraki;
    foreach(ubyte atomNumarası; 2..4) {
        //sonraki.atomuEkle(baştaki, atomNumarası);/*
        sonraki.başınaEkle(atomNumarası);//*/
    }
Böylece "Neden?" sorusuna (kısmen) cevap verilmiş oldu. Bunun daha zarif göründüğünü söylemeliyim...:)

Teşekkürler...
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-23, 14:03.
zafer #21
Üye Tem 2009 tarihinden beri · 700 mesaj · Konum: Ankara
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Yanıtlanan mesaj #19
Salih Dinçer:
(*) Eğer foreach() önüne yapının kopyasını birbirine eşitlemezseniz (baştaki = sonraki;) çalışma zamanı hatası verecektir!

Neden?

Doğrusu ikinci mesajını okuyana kadar baştaki = sonraki; satırını bulamamıştım. İkinci mesajı okuyunca ilgili satırı gördüm ve incelmeye başladım. Kodu kendimce yeniden şöyle düzenledim;

import std.stdio;
import std.string;
import std.conv;
 
struct Atom
{
    Atom* element;          // Eğer adres değeri F70 ile bitiyorsa,
    ubyte proton;           // 2. eleman türden bağımsız F74 oluyor
 
    this(Atom* a, ubyte b)
    {
        this.element = a;
        this.proton = b;
    }
 
    void atomuEkle(ref Atom* sonraki, ubyte değeri)
    {
        auto ekle = new Atom(null, değeri);
        sonraki.element = ekle;
        sonraki = ekle;
    }
 
    string toString() const
    {
        string tamami = format("%X -> %d", &proton, proton);
        if (element) tamami ~= "\n" ~ to!string(*element);
 
        return tamami;
    }
}
 
void main ()
{
    Atom* bastaki;
 
    Atom* sonraki = new Atom(null, 1);    // Hidrojen (en basit element!)
 
    bastaki = sonraki;
    foreach(ubyte atomNumarasi; 2..4)
    {
        sonraki.atomuEkle(bastaki, atomNumarasi);
    }
 
    writeln(to!string(*sonraki));
}

Öncelikle hatayı tespit edelim. Buradaki hata aşağıdaki metotda bulunan sonraki.element = ekle; satırından kaynaklanıyor.

void atomuEkle(ref Atom* sonraki, ubyte değeri)
{
    auto ekle = new Atom(null, değeri);
    sonraki.element = ekle;
    sonraki = ekle;
}

Bu metotda (sonraki.element = ekle;) satırında sonraki isimli göstergenin gösterdiği yapının element üye değişkenine ekle isimli düğümü aktarmak istiyorsun. Peki sonraki göstergesi nereden geliyor bakalım;

 foreach(ubyte atomNumarasi; 2..4)
    {
        sonraki.atomuEkle(bastaki, atomNumarasi);
    }

sonraki göstergesi aslında main() içinde tanımlanmış bastaki göstergesinin ta kendisi. Peki bastaki değişkeni bir düğümü gösteriyormu, eğer bastaki=sonraki; ataması yapılmamışsa tabi ki hayır.

İşte senin baştaki = sondaki; ataması ile yaptığın null olan bastaki göstergesine bir düğüm atamak ve dolayısıyla ilerleyen satırlarda bu düğüme ekleme yaparken üye değişkenlere ulaşabilme imkanına kavuşmak.

Biraz karıştırdım farkındayım :) Kısaca null olarak gönderdiğin bir değerden dolayı olay karışıyor.
https://github.com/zafer06 - depo
Avatar
Salih Dinçer #22
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Estağfirullah, ben karıştırmışım hatta parça parça kod vermek yerine kodun tamamını verseydim (yukarıda yazdıklarımı tekrarlamayım istedim) boşuna uğraştırmazdım...

Aslında GoLang'ın sitesinde olduğu gibi basit D kodlarını site üzerinde deneyebilseydik ne iyi olurdu değil mi? Düşünsenize kod etiketi içinde kalan bölümü script gibi derlemeden ekrana (ayrı bir pencereye) basan küçük bir düğme (run) olsaydı...:)
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
zafer #23
Üye Tem 2009 tarihinden beri · 700 mesaj · Konum: Ankara
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Salih Dinçer:
Aslında GoLang'ın sitesinde olduğu gibi basit D kodlarını site üzerinde deneyebilseydik ne iyi olurdu değil mi? Düşünsenize kod etiketi içinde kalan bölümü script gibi derlemeden ekrana (ayrı bir pencereye) basan küçük bir düğme (run) olsaydı...:)

İsteklerin sonu yok tabi :) Olabilir elbette neticede buda bir görüş ama benim ekrandaki kodu alıp kendi çalışma ortamıma aktarıp çalıştırmam sadece 5-10 saniyemi alıyor.
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:  önceki  1  2 
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-18, 07:37:28 (UTC -08:00)