これは、隣接リストのSO 投稿です。ただし、単一リンクリストとの違いはありませんか? また、これはウィキペディアの記事で、パスグラフではないグラフがある場合、リスト内のすべてのエッジ (グラフ、離散数学タイプ) であると述べています。隣接リストをコーディングするにはどうすればよいですか?
3 に答える
簡単な例:頂点タイプがあるとしますVertex
。グラフは頂点のセットで構成されており、次のように実装できます。
std::unordered_set<Vertex> vertices;
ここで、グラフにエッジがある頂点のペアごとに、そのエッジを記録する必要があります。隣接リスト表現では、頂点のペアである可能性のあるエッジタイプを作成し、隣接リストは単にそのようなエッジのリスト(またはセット)である可能性があります。
typedef std::pair<Vertex, Vertex> Edge;
std::list<Edge> edges_as_list;
std::unordered_set<Edge> edges_as_set;
(無向グラフ(a,b) == (b,a)
がある場合は、最後のセットに無向コンパレータを提供することをお勧めします。)
一方、隣接行列表現を作成する場合は、代わりにboolの配列を作成し、それらの間にエッジがある頂点を示します。
bool edges_as_matrix[vertices.size()][vertices.size()]; // `vector` is better
// edges_as_matrix[i][j] = true if there's an edge
(このためには、頂点を列挙する方法が必要になります。無向グラフでは、隣接行列は対称です。有向グラフでは、対称である必要はありません。)
エッジが少ない場合はリスト表現が適していますが、エッジが多い場合はマトリックス表現が適しています。
struct Node {
std::vector<std::shared_ptr<Node>> Neighbors;
};
struct AdjacencyList{
std::vector<std::shared_ptr<Node>> Nodes;
};
AdjacencyList
すべての の配列を保持し、Node
それぞれNode
がリスト内の他のすべての へのリンクを持っていますNode
。技術的にはAdjacencyList
クラスは必須ではなく、必要なのは astd::shared_ptr<Node> root;
だけですが、 a を持つ theAdjacencyList
を使用するとvector
、それらを反復処理したり、他の多くのことをはるかに簡単に実行したりできます。
A----B F | |\ | | \ C D--E
AdjacencyList
A
、B
、C
、D
、E
、およびへのポインタを保持しますF
。
A
と へのポインタがB
ありC
ます。とへの
B
ポインタがA
あります。へのポインタがあります。と へのポインタがあります。 と へのポインタがあります。他のノードへのポインタはありません。D
E
C
A
D
B
E
E
B
D
F
AdjacencyList には、Node
値ではなくポインターを含める必要があります。そうしないと、サイズが変更されると、すべてのNeighbors
ポインターが無効になります。
そのため、Boost には、boost::graph の一部として adjacency_list コンテナーが含まれています。
一般に、隣接リストは単独でリンクされたリスト以上のものです。これは、任意の頂点からグラフ内の他の頂点への (場合によっては、特定の方向の) 直接接続を表します。
ブーストのドキュメントには、いくつかの基本的な例が写真付きで提供されています。