Bir grafik veri yapısını uygulamak için en fazla yer tasarrufu sağlayan yöntem nedir?


14

Ben tipik olarak çift bağlantılı listeleri olarak grafikler uygulamak ama benim deneyim oldukça boşluk verimsiz k k komşular için k işaretçileri / referansları gerekir, bu yüzden yönlendirilmemiş bir grafik için matematik doğru ise ben listeleri içinde ~ 2k komşu bağlantıları olurdu. Yerden tasarruf etmenin daha iyi bir yolu var mı? Grafik yönlendirilirse bazı bağlantıların tekil yapılabileceğini biliyorum, ancak bunun daha iyi bir iş yapmanın bir yolu var mı?

Yanıtlar:


12

Yer verimliliği umursadığınız her şey varsa o zaman sıkıştırılmış bir veri yapısı en iyi olurdu - ama elbette bu erişim veya güncelleme için çok verimli değil .....

Grafiğinizin nispeten az sayıda düğümü varsa ve oldukça yoğunsa (diyelim ki tüm olası bağlantıların en az% 5'i var), kenar listelerini kullanmak yerine bir bitişiklik matrisi oluşturmanın daha fazla alan etkili olduğunu görebilirsiniz . Bu, olası (yönlendirilmiş) bağlantı başına yalnızca bir bit ve n düğümünüz olduğunda toplam n * n bit gerektirir.

Aksi takdirde, komşu bağlantıları kullanmanız gerekiyorsa, bu, saklamanız gereken minimum bilgi içeriği olduğundan bağlantı başına bir referanstan daha kolay bir şekilde daha iyi yapamazsınız. Geri bağlantılar istiyorsanız, iki kat daha fazla bağlantıya ihtiyacınız olacaktır.

Bunun üzerinde deneyebileceğiniz bazı püf noktaları var. Örneğin, bağlantı alt kümelerini paylaşmayı deneyebilirsiniz (A ve B, C, D, E'nin her birine atıfta bulunuyorsa, yalnızca C, D, E bağlantılarının listesini bir kez saklayın .....). Ancak bu oldukça hızlı bir şekilde karmaşıklaşacak ve çoğu durumda çabaya değeceğinden şüpheliyim.

Başka bir hile - grafiğinizin makul sayıda düğüme sahip olduğu varsayılarak, kesinlikle indeksleyerek yerden tasarruf edersiniz - örneğin, tam bir işaretçi / referans yerine 16 bit düğüm dizin numarası kullanarak.


Tüm bağlantılar yönlendirilmezse, yalnızca kenarı düşük düğümden yüksek düğüme kaydederek alanın yarısını koruyabilirsiniz.
Tekilleştirici

6

Verilerinizin yapısına bağlı olacaktır.

Yönlendirilmemiş kenarları olan yoğun bir grafik için, üçgen bir matrisi temsil eden bit dizilerinin bir listesini gerçekten yenemezsiniz. List<BitArray>Örneğin A. Mantıken, şöyle görünecektir:

 0123
0
11
211
3001
41010

Oradan, düğüm verilerinizi depolayan bir listeye dizinlemek için kök BitArray dizinini kullanabilirsiniz.

Örneğin, bir düğümün tüm komşularını almak şu şekilde olur:

// C#
List<Node> Nodes = /* populated elsewhere */
List<BitArray> bits = /* populated elsewhere */
public static IEnumerable<Node> GetNeighbours(int x)    
{
    for (int i = 0; i < bits[idx].Count; i++)
    {
        if (this.bits[idx][i])
            yield return this.Nodes[i];
    }

    for (int i = 0; i < this.Nodes.Count; i++)
    {
        if (idx < this.bits[i].Count && this.bits[i][idx])
            yield return this.Nodes[i];
    }    
}

(veri miktarına bağlı olarak, tüm dizinler pozitif olacağından, bir bayt veya ushort veya bu satırlar boyunca bir şey olarak dizin türünü de seçebileceğinizi unutmayın. Önemsiz olduğu için bunu bir mikro optimizasyon olarak düşünmüyorum)

Yönlendirilmiş bir grafik için, bağlantıyı saklamak için bir * n bit dizisinin yolunu seçersiniz ... bitişik bir dizin listesine gidebileceğiniz düğüm sayısına kıyasla çok seyrek değilse.

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.