Apa cara paling efisien untuk mengimplementasikan struktur data grafik?


14

Saya biasanya menerapkan grafik sebagai daftar yang ditautkan dua kali lipat, tetapi ini cukup tidak efisien dalam pengalaman saya karena saya memerlukan k pointer / referensi untuk k tetangga sehingga untuk grafik yang tidak terarah saya akan memiliki ~ 2k tautan tetangga dalam daftar jika matematika saya benar. Apakah ada cara yang lebih baik untuk menghemat ruang? Saya tahu bahwa beberapa tautan dapat dibuat tunggal jika grafik diarahkan tetapi apakah ada cara untuk melakukan pekerjaan ini dengan lebih baik?

Jawaban:


12

Baik jika efisiensi ruang adalah yang Anda pedulikan maka struktur data terkompresi akan lebih baik - tetapi tentu saja ini tidak sangat efisien untuk akses atau pembaruan .....

Jika grafik Anda memiliki jumlah node yang relatif kecil dan cukup padat (katakanlah setidaknya 5% dari semua koneksi yang mungkin ada) maka Anda mungkin menemukan lebih banyak ruang efisien untuk membuat matriks adjacency daripada menggunakan daftar tepi. Ini akan membutuhkan hanya satu bit per kemungkinan koneksi (diarahkan), dan n * n bit total di mana Anda memiliki n node.

Kalau tidak, jika Anda perlu menggunakan tautan tetangga maka Anda tidak dapat dengan mudah melakukan lebih baik dari satu referensi per tautan karena ini adalah konten informasi minimum yang Anda perlukan untuk menyimpan. Jika Anda ingin back-link Anda akan membutuhkan dua kali lebih banyak tautan.

Ada beberapa trik yang bisa Anda coba di atas ini. Misalnya, Anda dapat mencoba berbagi subset tautan (jika A dan B merujuk ke masing-masing C, D, E maka hanya menyimpan daftar tautan C, D, E sekali .....). Namun ini akan menjadi kompleks dengan cukup cepat dan saya ragu itu akan sepadan dengan usaha dalam banyak kasus.

Satu trik lain - dengan asumsi grafik Anda memiliki jumlah node yang masuk akal, Anda tentu akan menghemat ruang dengan mengindeks - misalnya menggunakan nomor indeks node 16-bit daripada pointer penuh / referensi.


Jika semua tautan tidak diarahkan, seseorang dapat menghemat setengah ruang dengan hanya menyimpan ujung dari titik rendah ke titik tinggi.
Deduplicator

6

Ini akan tergantung pada struktur data Anda.

Untuk grafik yang padat dengan tepi yang tidak terarah, Anda tidak bisa mengalahkan daftar bit array yang mewakili matriks segitiga. A List<BitArray>misalnya. Logikanya, akan terlihat seperti ini:

 0123
0
11
211
3001
41010

Dari sana, Anda dapat menggunakan indeks root BitArray untuk mengindeks ke daftar yang menyimpan data simpul Anda.

Misalnya, mendapatkan semua tetangga dari simpul akan seperti:

// 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];
    }    
}

(perhatikan bahwa Anda juga dapat memilih jenis indeks, tergantung pada jumlah data, menjadi byte atau ushort atau sesuatu di sepanjang baris tersebut karena semua indeks akan positif. Saya tidak menganggap ini sebagai optimasi mikro karena sepele)

Untuk grafik yang diarahkan, Anda akan pergi rute array * n bit untuk menyimpan konektivitas ... kecuali itu sangat jarang dibandingkan dengan jumlah node, di mana Anda dapat pergi ke daftar indeks kedekatan.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.