web-dev-qa-db-ja.com

Java:グラフの表現方法

グラフとその操作方法について学ぶために、いくつかのアルゴリズムを実装しています。 Javaでそれを行う最良の方法は何ですか?私はこのようなことを考えていました:

public class Vertex {

    private ArrayList<Vertex> outnodes; //Adjacency list. if I wanted to support Edge weight, this would be a hash map.

    //methods to manipulate outnodes
}

public class Graph {
    private ArrayList<Vertex> nodes;
    //algorithms on graphs
}

しかし、私は基本的にこれを構成しました。もっと良い方法はありますか?

また、ダイグラフ、重み付きエッジ、マルチグラフなどのバニラグラフのバリエーションをサポートできるようにしたいです。

43
Nick Heiner

各ノードには一意の名前が付けられ、誰に接続されているかがわかります。接続のリストでは、Nodeを任意の数の他のノードに接続できます。

public class Node {
    public String name;
    public List<Edge> connections;
}

各接続は方向付けられ、開始点と終了点があり、重み付けされています。

public class Edge {
    public Node start;
    public Node end;
    public double weight;
}

グラフは単なるノードのコレクションです。の代わりに List<Node>検討Map<String, Node>名前による高速検索。

public class Graph {
    List<Node> nodes;
}
30
bhspencer

重み付きエッジとマルチグラフが必要な場合は、別のクラスを追加することもできますEdge

また、genericsを使用して、現在使用されている頂点とエッジのサブクラスを指定できるようにすることをお勧めします。例えば:

public class Graph<V extends Vertex> {
List<V> vertices;
...
}

グラフアルゴリズムの実装に関しては、アルゴリズムが動作できるグラフクラスのinterfacesを定義することもできます。実際のグラフ表現の実装。たとえば、適切に接続された単純なグラフは隣接行列でより適切に実装でき、より疎なグラフは隣接リスト-それはすべて依存しています...

ところで、このような構造を効率的に構築することは非常に困難な場合があるため、どのような種類の仕事に使用したいのか、詳細を教えていただけますか?より複雑なタスクについては、インスピレーションを得るために、さまざまなJavaグラフライブラリをご覧になることをお勧めします。

16
Roland Ewald

http://jung.sourceforge.net/doc/index.html グラフライブラリをご覧ください。独自のアルゴリズムの実装を練習することもできます(開始するには幅優先または深さ優先の検索かもしれません)が、グラフ構造の作成について心配する必要はありません。

6
Jeff Storey

物事をシンプルに保ち、 隣接行列 または 隣接リスト を使用しないのはなぜですか?

4
andrewkshim

この質問の時でさえ、3年以上前に、 Sage (これは完全に無料です)が存在し、グラフ理論がかなり上手でした。しかし、2012年には、最高のグラフ理論ツールが存在します。したがって、Sageにはすでに、他の無料でオープンソースのものを含む、大量のグラフ理論資料が組み込まれています。そのため、プログラミングを必要としないため、さまざまなことをいじってより多くのことを学ぶのは簡単です。

また、プログラミングの部分にも興味がある場合、最初のSageはオープンソースなので、既存のコードを確認できます。そして、第二に、本当に練習したい場合は、必要な機能を再プログラムするか、まだ存在しないものを最初にプログラムすることができます。後者の場合、その新しい機能を送信して、他のすべてのユーザーにとってSageを改善することさえできます。

現時点では、この回答はOPにとってはそれほど有用ではないかもしれません(3年前から)が、将来この質問を見る他の人にとっては有益であることを願っています。

2
Graphth

グラフをレンダリングするポイントに到達したら、 graphviz を強くお勧めします。

そしてその仲間: notugly.xls とともに Laszlo SzathmaryのGraphVizクラス を見てください。

2
duffymo

昔、私は同じ問題を抱えていて、自分で実装しました。別のクラスを実装することをお勧めします:エッジ。次に、頂点にはエッジのリストがあります。

public class Edge {
    private Node a, b;
    private directionEnum direction;     // AB, BA or both
    private int weight;
    ...
}

それは私のために働いた。しかし、たぶんとても簡単です。コードを調べると役立つライブラリがあります。 http://jgrapht.sourceforge.net/

2
sinuhepop
class Graph<E> {
    private List<Vertex<E>> vertices;

    private static class Vertex<E> {
        E elem;
        List<Vertex<E>> neighbors;
    }
}

Graphの隣接リスト実装は、グラフ関連の問題のほとんどを解決するのに適しています。

同じもののJava実装は、私のブログでは here です。

1
rai.skumar

「ロバート・セジウィック」と「ケビン・ウェイン」によって書かれた簡単な表現は、 http://algs4.cs.princeton.edu/41graph/Graph.Java.html で入手できます。

上記のページからコピーされた説明。

Graphクラスは、0〜[〜#〜] v [〜#〜]-1という名前の頂点の無向グラフを表します。

次の2つの主要な操作をサポートしています。エッジをグラフに追加し、頂点に隣接するすべての頂点を反復処理します。また、頂点の数[〜#〜] v [〜#〜]およびエッジの数[〜#〜] e [〜#〜]。平行エッジと自己ループが許可されます。慣例により、自己ループv-vが隣接に表示されますvのリストを2回作成し、vの次数に2を提供します。

この実装では、隣接リスト表現を使用します。これは、Bagオブジェクトの頂点インデックス付き配列です。与えられた頂点に隣接する頂点を反復処理する場合を除き、すべての操作には一定の時間がかかります(最悪の場合)。そのような頂点の数に比例して時間がかかります。

0
Rajani Karuturi