web-dev-qa-db-ja.com

BFSおよびDFSのランタイムの説明

特に、次のサイトのこの例のように、頂点から到達できるノードに向けられたエッジを持つノードがある場合、BFSおよびDFS O(V + E)の実行時間はなぜですか

http://www.personal.kent.edu/~rmuhamma/Algorithms/MyAlgorithms/GraphAlgor/depthSearch.htm

36
miss24

Eは、G = {V、E}のように、グラフ内のすべてのエッジのセットです。したがって、| E |グラフ内のすべてのエッジの数です。

これだけで、全体的な複雑さが| V |にならないことを確信させるのに十分なはずです。これは、各頂点のグラフのすべてのエッジを反復処理していないためです。

隣接リスト表現では、各頂点vについて、それに隣接するノードのみを走査します。

| V | | V | + | E |の係数実行されたキュー操作の数に起因するようです。

アルゴリズムの複雑さは、使用するデータ構造に依存することに注意してください。事実上、グラフの表現に存在する各情報にアクセスしているため、グラフのマトリックス表現では、複雑度はVの2乗になります。

コーメンから引用して、

「エンキューおよびデキューの操作には、O(1)時間を要するため、キュー操作に費やされる合計時間はO(V)です。各頂点の隣接リストは、頂点がすべての隣接リストの長さの合計がΘ(E)であるため、隣接リストのスキャンに費やされる合計時間はO(E)です。初期化のオーバーヘッドはO( V)、したがってBFSの合計実行時間はO(V + E)です。」

40

この問題は私の時間の4時間ほどを消費しますが、最終的には写真を撮る簡単な方法があると思います。最初はO(V * E)と言いたくなりました。

Cormenで見つけたアルゴリズムを要約すると、それは http://www.personal.kent.edu/~rmuhamma/Algorithms/MyAlgorithms/GraphAlgor/breadthSearch.htm で同じです:

for(vi in V)Some O(1) instructions for(e in Adj(vi))){Some O(1) instructions}

問題は、ここで実行される命令の数です。それはSigma-Sum(Adj(vi))になり、この値の上限は2 | E |になります。

最初は、内部ループと外部ループの反復回数を乗算することを自動的に考えますが、この場合、内部ループの反復の合計数は外部反復子の関数であるため、乗算は不可能です。

18
Jose Francisco

すべてのEdgeに最大2回アクセスします。 Eエッジがあります。そのため、2 * E Edgeの訪問操作が行われます。さらに、ノードにはエッジがない、つまり次数0のノードがあります。最大でV個のノードが存在できます。したがって、複雑さはO(2 * E + V)= O(E + V)

8
Fallen

隣接リストとして表されるデータ構造としてグラフを見ると明らかになります

enter image description here

頂点:A、B、C、D、E、および各頂点/ノードの隣接する頂点が、それらの頂点からのリストとして表示されます。循環グラフの場合に「訪問」されたかどうかをチェックするには、すべてのボックスを「表示」する必要があります。グラフのようなツリーの場合は、すべての子を通過します。

0
AleC

| V |を反復処理します最大で| V |のノード回。 | E |の上限があるためグラフ内の合計エッジ、最大で| E |をチェックします。エッジ。異なる頂点には隣接するノードの数が異なるため、cannot単に| V | * | E |を乗算します(つまり、各頂点について| E |エッジをトラバースしますが、これは真ではありません。| E |はすべてのノードのエッジの総数です)、Vノードをチェックし、合計Eをチェックしますエッジ。最後に、O(| V | + | E |)があります

DFSについても同様です。すべての頂点隣接リストをループし、DFS(v)が呼び出されていない場合は呼び出します。つまり、| V |が発生します。タイムステップに加えて、隣接ノードを訪問するためにかかった時間(本質的に、これらはエッジを形成し、合計| E |エッジがあるため、O(V + E)時間です。

    private static void visitUsingDFS(Node startNode) {
        if(startNode.visited){
            return;
        }
        startNode.visited = true;
        System.out.println("Visited "+startNode.data);
        for(Node node: startNode.AdjacentNodes){
            if(!node.visited){
                visitUsingDFS(node);
            }
        }
    }
0
Bavinho