Dönüşüm hiyerarşisini temsil etmek için verimli yapı


9

Herkes, örneğin bir hiyerarşi modelinde, bir matris ağacını temsil etmek için bellek verimli bir yol önerebilir mi?

Özellikle veri konumunu korumaya hevesliyim ve dizilerin bir yapısı (matrisler ve matrislere endeksler) tipi yaklaşımın uygun olabileceğinden şüpheleniyorum.

Birçok zincirleme matris hesaplamasının yanı sıra, bu yapı muhtemelen bellekte adil bir şekilde kopyalanacaktır, bu nedenle bitişik depolamaya sahip olmak büyük bir bonus olacaktır.

Yanıtlar:


6

Dizi olarak ağaç bana bir galibiyet gibi geliyor. Sadece hiyerarşinizin derinlikli ilk geçişini yapın ve bir dizi doldurun; özyinelemeyi geri sararken, ebeveyni mutlak endeksle çocuğa güncelleyebilir ya da sadece benden delta yapabilir ve çocuklar ebeveyn dizinlerini de her iki şekilde de saklayabilir. Gerçekten de, göreli ofsetler kullanırsanız, o zaman kök adresini taşımanız gerekmez. Sanırım bu yapı muhtemelen

struct Transform
{
   Matrix m; // whatever you like
   int parent;   // index or offset, you choose!
   int sibling;
   int firstchild;
};

... yani değişken bir yapıya sahip olamayacağınız için kardeşlere nasıl ulaşacağınızı bilmek için düğümlere ihtiyacınız olacak. Dönüşüm ofsetleri yerine bayt ofsetleri kullandıysanız, dönüşüm başına değişken sayıda çocuğunuz olabilir:

struct Transform
{
   Matrix m; // whatever you like
   int parent;  // negative byte offest
   int numchildren;
   int child[0]; // can't remember if you put a 0 there or leave it empty;
                 // but it's an array of positive byte offsets
};

... o zaman birbirini takip eden Dönüşümleri doğru yere koyduğunuzdan emin olmalısınız.

Katıştırılmış alt "işaretçiler" ile tamamen müstakil bir ağaç oluşturmak için.

int BuildTransforms(Entity* e, OutputStream& os, int parentLocation)
{
    int currentLocation = os.Tell();

    os.Write(e->localMatrix);
    os.Write(parentLocation);
    int numChildren = e->GetNumChildren();
    os.Write(numChildren);

    int childArray = os.Tell();
    os.Skip(numChildren * sizeof(int));
    os.AlignAsNecessary();  // if you need to align transforms

    childLocation = os.Tell();
    for (int i = 0; i < numChildren; ++i) {
        os.Seek(childArray + (i * sizeof(int)));
        os.Write(childLocation);
        os.Seek(childLocation);
        childLocation = BuildTransforms(e->GetChild(i), os, currentLocation);
    }

    return os.Tell();
}

void BuildTransforms(Entity* root)
{
    OutputStream os;
    BuildTransforms(root, os, -1, 0);
}

(Göreli konumları saklamak istiyorsanız - currentLocation, iki "konum" yazmasına ekleyin .)


C ++ ile konuşuyorsanız, alt diziniz için bir boyut belirtmeniz veya çalışma zamanında bir bellek ayırma ile oluşturmanız gerekir.
tenpn

C99 onaylı resmi yol, dizi boyutu belirtimini boş bırakmaktır.

@ tenpn- buradaki amaç, özel olarak oluşturulmuş bir ara belleğe sahip olmanız. Bütün mesele ekstra tahsislerden kaçınmaktır ; dizi boyutunu belirtemezsiniz, çünkü ne kadar büyük olacağını bilmezsiniz. Num children yazdıktan sonra, alt dizinize yazarsınız, ancak alt dizi sona erdikten sonra bir sonraki Dönüştürme başlar. (Bu nedenle, bu yapı için endeksleri değil, bayt ofsetlerini kullanmanız gerekir; her bir girişin ne kadar büyük olduğunu bilmiyorsunuz, ancak geçiş yapmak hala verimli ve kendi içinde kalıyor, böylece bir birim olarak hareket edebiliyor.)
tire -tom-bang

1
Buna "yapı korsanlığı" denir. Ayrıca bkz: informit.com/guides/content.aspx?g=cplusplus&seqNum=288
Neverender

1
@tenpn Aka değişken uzunluklu yapılar. Uygun şekilde kullanıldıklarında yığın tahsisi sayısını yarıya indirebilirler.

1

Matris dizisine endeksleme, muhtemelen en basit, hafızayı verimli kullanan yaklaşım olacaktır.

Bir dönüşüm zinciri bir LIFO içinde bir dizi işaretçi veya tamsayı veya matris dizisine indekslenen diğer küçük yapı olarak tutulabilir. Bu, yedek matrislerin depolanmasını önlemeye yardımcı olur ve veri depolama kodunu veri erişim kodundan ayırır.

Sonuçta, dönüşüm zincirinizi saklamak veya oynatmak için LIFO'daki indeks değerlerini itip pop.

Matris yapınız ayrıca dönüştürme türü ... döndürme, çeviri vb. İçerebilirse, biraz bellek tasarrufu da sağlayabilirsiniz. Aksi takdirde, türün dizinle birlikte depolanması gerekir, bu da daha fazla çoğaltma ile sonuçlanır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.