Nesne grafik gösterimini bitişiklik listesi ve matris temsilleriyle karşılaştırma


82

Şu anda Steve Yegge'in teknik programlama röportajına hazırlanmayla ilgili tavsiyesini uyguluyorum: http://steve-yegge.blogspot.com/2008/03/get-that-job-at-google.html

Grafiklerle ilgili bölümünde şunları söylüyor:

Bellekte bir grafiği temsil etmenin üç temel yolu vardır (nesneler ve işaretçiler, matris ve bitişiklik listesi) ve her bir temsil ile artılarını ve eksilerini öğrenmelisiniz.

Matris ve bitişik liste temsillerinin artıları ve eksileri CLRS'de açıklanmıştır, ancak bunları bir nesne temsiliyle karşılaştıran bir kaynak bulamadım.

Sadece düşünerek, bunun bir kısmını kendim çıkarabilirim, ancak önemli bir şeyi kaçırmadığımdan emin olmak isterim. Birisi bunu kapsamlı bir şekilde tanımlayabilirse veya beni bunu yapan bir kaynağa yönlendirebilirse, çok memnun olurum.


nasıl endüktif grafikler - altında bu sonbaharda yapmak 3 kategoriden?
Erik Kaplun

Yanıtlar:


94

nesneler ve işaretçiler

Bunlar, hammar'ın diğer yanıtta söylediği gibi temel veri yapılarıdır, Javabunu kenarlar ve köşeler gibi sınıflarla temsil edersiniz. Örneğin, bir kenar iki köşeyi birbirine bağlar ve yönlendirilebilir veya yönsüz olabilir ve bir ağırlık içerebilir. Bir tepe noktasının kimliği, adı vb. Olabilir. Çoğunlukla her ikisinin de ek özellikleri vardır. Böylece grafiğinizi onlarla şöyle oluşturabilirsiniz:

Vertex a = new Vertex(1);
Vertex b = new Vertex(2);
Edge edge = new Edge(a,b, 30); // init an edge between ab and be with weight 30  

Bu yaklaşım genellikle nesne yönelimli uygulamalar için kullanılır, çünkü nesne yönelimli kullanıcılar için daha okunabilir ve daha uygundur;).

matris

Bir matris sadece 2 boyutlu basit bir dizidir. Bunun gibi bir int dizisi olarak temsil edilebilen köşe kimlikleriniz olduğunu varsayarsak:

int[][] adjacencyMatrix = new int[SIZE][SIZE]; // SIZE is the number of vertices in our graph
adjacencyMatrix[0][1] = 30; // sets the weight of a vertex 0 that is adjacent to vertex 1

Bu, genellikle dizin erişiminin gerekli olduğu yoğun grafikler için kullanılır. Bununla yönlendirilmemiş ve ağırlıklı bir yapıyı temsil edebilirsiniz.

bitişiklik listesi

Bu sadece basit bir veri yapısı karışımı, genellikle bunu bir HashMap<Vertex, List<Vertex>>. HashMultimapGuava'da da benzer şekilde kullanılabilir .

Bu yaklaşım harika, çünkü O (1) (amortize edilmiş) köşe aramanız var ve bana talep ettiğim bu belirli köşeye tüm bitişik köşelerin bir listesini döndürüyor.

ArrayList<Vertex> list = new ArrayList<>();
list.add(new Vertex(2));
list.add(new Vertex(3));
map.put(new Vertex(1), list); // vertex 1 is adjacent to 2 and 3

Bu, seyrek grafikleri temsil etmek için kullanılır, Google'a başvuruyorsanız, web grafiğinin seyrek olduğunu bilmelisiniz. Bir BigTable kullanarak onlarla daha ölçeklenebilir bir şekilde başa çıkabilirsiniz .

Oh ve BTW, işte bu yazının süslü resimlerle çok iyi bir özeti;)


Bu yaklaşım harika, çünkü O (1) köşe aramanız var, bu karmaşıklık biraz yanlış, özellikle de O (1 + alfa), burada alfa = hash map / köşe sayısındaki yuva sayısı. Bu nedenle, karma harita yerine dizi kullanmayı öneriyorum
Timofey

@Tim O (1) itfa edilmiştir. Karmaşıklık hesaplamanız büyük ölçüde uygulamaya bağlıdır. HashMap( Docs.oracle.com/javase/7/docs/api/java/util/HashMap.html ) adresinin javadoc'una bakın : This implementation provides constant-time performance for the basic operations= O (1) amorti edildi.
Thomas Jungblut

6
@Tim Sanırım buradaki herkes dizi erişiminin herhangi bir HashTablekullanımdan daha hızlı olduğunu biliyor . Bu yüzden ihmal edilebilecek küçük bir sabit alfa ek yüküyle etrafı karıştırmaya gerek yok.
Thomas Jungblut

2
Lütfen beni yanlış anlamayın, güzel cevabınızı gücendirmiyorum, ama cevabınızın iyileştirilebileceğine dair bir his var, öyleyse neden burada bahsetmeyelim :)
Timofey

2
@Tim Amortize edilmiş notu cevaba ekledim. Teşekkürler.
Thomas Jungblut

7

Nesneler ve işaretçiler, en azından bu gösterimleri kullanan algoritmaları karşılaştırmak amacıyla, çoğunlukla bitişik listeyle aynıdır.

Karşılaştırmak

struct Node {
    Node *neighbours[];
};

ile

struct Node {
    Node *left;
    Node *right;
};

İkinci durumda, adlandırılmış işaretçilerle çalışmak daha kolaysa, komşular listesini anında kolayca oluşturabilirsiniz.



1

Başka bir iyi kaynak: Khan Academy - "Grafikleri Temsil Etmek"

Bitişiklik listesi ve bitişiklik matrisinin yanı sıra, "kenar listelerini" 3. tip grafik gösterimi olarak listelerler. Bir uç liste, Thomas'ın "nesneler ve işaretçiler" yanıtındakiler gibi "uç nesnelerin" bir listesi olarak yorumlanabilir.

Avantaj: Kenar hakkında daha fazla bilgi saklayabiliriz (Michal tarafından bahsedilmiştir)

Dezavantaj: Çalışması çok yavaş bir veri yapısı:

  • Bir kenar arayın: O (log e)
  • Bir kenarı kaldırın: O (e)
  • Belirli bir düğüme bitişik tüm düğümleri bulun: O (e)
  • İki düğüm arasında bir yol olup olmadığını belirleyin: O (e ^ 2)

e = kenar sayısı

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.