現在、技術プログラミングインタビューの準備に関するSteve Yeggeのアドバイスに従っています。 http://steve-yegge.blogspot.com/2008/03/get-that-job-at-google.html
グラフに関するセクションで、彼は次のように述べています。
メモリ内のグラフを表す3つの基本的な方法(オブジェクトとポインター、マトリックス、隣接リスト)があり、各表現とその長所と短所をよく理解する必要があります。
マトリックスと隣接リストの表現の長所と短所はCLRSで説明されていますが、これらをオブジェクト表現と比較するリソースを見つけることができませんでした。
それについて考えるだけで、このことのいくつかを自分で推測することができますが、何か重要なことを見逃していないことを確認したいと思います。誰かがこれを包括的に説明したり、そうするリソースを教えてくれたりしたら、とても感謝しています。
オブジェクトとポインター
これらは、他の回答で述べたhammarのような基本的なデータ構造にすぎません。Java
では、これをエッジや頂点などのクラスで表します。たとえば、エッジは2つの頂点を接続し、有向または無向のいずれかで、ウェイトを含めることができます。頂点はID、名前などを持つことができます。ほとんどの場合、両方に追加のプロパティがあります。したがって、次のようにグラフを作成できます
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
このアプローチは、オブジェクト指向のユーザーにとって読みやすく便利なため、オブジェクト指向の実装によく使用されます;)。
マトリックス
マトリックスは、単純な2次元配列です。次のようなint配列として表現できる頂点IDがあると仮定します。
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
これは通常、インデックスアクセスが必要な密なグラフに使用されます。これにより、非/有向および重み付けされた構造を表すことができます。
隣接リスト
これは単純なデータ構造のミックスであり、通常はHashMap<Vertex, List<Vertex>>
。同様に、グアバのHashMultimap
を使用できます。
O(1)(償却済み)頂点ルックアップがあり、私が要求したこの特定の頂点に隣接するすべての頂点のリストを返します。
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
これは、スパースグラフの表現に使用されます。Googleで申請している場合、ウェブグラフがスパースであることを知っておく必要があります。 BigTable を使用すると、よりスケーラブルな方法でそれらに対処できます。
ああ、ところで、 ここ は、この投稿の素晴らしい写真の要約です;)
少なくともこれらの表現を使用するアルゴリズムを比較する目的では、オブジェクトとポインターはほとんど隣接リストと同じです。
比較する
struct Node {
Node *neighbours[];
};
と
struct Node {
Node *left;
Node *right;
};
後者の場合、名前付きポインターよりも作業が簡単な場合は、その場で隣人のリストを簡単に作成できます。
オブジェクト表現( incidence list )の利点は、2つの隣接する頂点が同じEdgeインスタンスを共有することです。これにより、無向のエッジデータ(長さ、コスト、フロー、さらには方向)を簡単に操作できます。ただし、ポインターに余分なメモリを使用します。
別の優れたリソース: Khan Academy-"Representing Graphs"
隣接リストと隣接マトリックスに加えて、3番目のタイプのグラフ表現として「エッジリスト」をリストします。エッジリストは、トーマスの「オブジェクトとポインター」の回答にあるような「エッジオブジェクト」のリストとして解釈できます。
利点:Edgeに関する詳細情報を保存できます(Michalが言及)
短所:使用するには非常に遅いデータ構造です。
e =エッジの数