2013-04-23 9 views
6

グラフを表現する方法は2つあります.1つは行列を使用し、もう1つはリストを使用することです。線形時間でグラフを逆転させるには?

私が行列を使用する場合、行列のすべてのビットを反転する必要があります。それはO(V^2)時間かかりませんか?

私はリストを使用している場合は、私は、一つ一つがそれぞれのリストを横断して、新しいセットを作成する必要はありませんでしょうか?それは直線的なO(V + E)時間を取るように思われる。私は正しいですか?

私はここで別の質問があります。たとえば、グラフ(マトリックスまたはリストのいずれか)にDijkstraアルゴリズムを使用し、シーンの背後にあるデータ構造に優先キューを使用するとします。グラフの表現とデータ構造の関係はありますか?それはアルゴリズムのパフォーマンスに影響を与えますか?

私が表現してダイクストラアルゴリズムのための優先順位キューのリストを使用していたと仮定し、ダイクストラのための行列と利用プライオリティキューの違いがあるでしょうか?

私はそれだけでmakeQueue操作に関連すると思いますか?それとも全く違うのではないでしょうか?

+0

隣接リストのトラバーサルは、E = O(V^2)などの一般的な線形時間では発生しません。 – collapsar

+0

@ collapsar It * always *は、頂点*とエッジ*との関係で線形時間に発生します。時間の複雑さを定義するのは、時間の複雑さを明示的に述べることなく、入力の一部(つまり、ちょうど頂点)で定義することは、時間が入力の別の部分に直接関係している場合には、あなたがしたように人々はそれを定義することができます)。そしてE = O(V^2)は密なグラフのためのものです。スパースグラフはE = O(V)です。 – Dukeling

+0

@dukeling問題の「サイズ」を単一のスカラーに減らすことは、精度の欠如を伴うことを指摘しています。 otoh、big-Oh表記は最悪の場合を記述し、グラフを考慮して、追加の制約なしに最悪の場合はE = O(V^2)を意味する。正確には、O(V^2)は隣接行列上のエッジの逆転に対しても正しくない - 表現がフラグ行 - メジャーとコ - メジャーをスポーツする場合、転置はO(1)である。 – collapsar

答えて

19

は線形時間で行うことができます。グラフを1回だけトラバースします。複雑さの順序はO(| V | + | E |)になります。

  1. キーが頂点ラベルで、値がキー頂点の隣接する頂点のArrayListである、AdjacenyリストのHashMapを維持します。
  2. 逆の場合、同じ種類の新しいHashMapを作成します。元のハッシュマップをスキャンし、見つかったキーごとに対応するリストをトラバースします。値リストにある各頂点について
  3. 、新しいハッシュマップ内の新しいキーに対応するArrayListの中にエントリとして元のハッシュマップのキーを入れ、新しいハッシュマップにキーを追加します。
public static HashMap<Character,ArrayList <Character>> getReversedAdjLists(RGraph g) 
{ 
    HashMap <Character, ArrayList<Character>> revAdjListMap = new HashMap <Character, ArrayList<Character>>(); 
    Set <Character> oldLabelSet = g.adjListMap.keySet(); 

    for(char oldLabel:oldLabelSet) 
    { 
     ArrayList<Character> oldLabelList = g.adjListMap.get(oldLabel); 

     for (char newLabel : oldLabelList) 
     { 
      ArrayList<Character> newLabelList = revAdjListMap.get(newLabel); 

      if (newLabelList == null) 
      { 
       newLabelList = new ArrayList<Character>(); 
       newLabelList.add(oldLabel); 
      } 
      else if (! newLabelList.contains(oldLabel)) 
      { 
       newLabelList.add(oldLabel); 
      } 

      revAdjListMap.put(newLabel, newLabelList); 
     } 
    } 

    return revAdjListMap; 
} 
+0

良い答えです。私は当初、静的な2D配列でこれをしようとしていましたが、その行列の転置(反転を達成するため)はO(n^2)です。私はかなり確信しています。 – scottyseus

0

グラフを反転させるには、O(V )が必要です。なぜなら各頂点について、(V-1)個のエッジを追加または削除する必要があるからです。

Dijkstraのアルゴリズムについては、グラフを行列またはリストとして表現するとO(V )が必要ですが、他のデータ構造も高速です。最も速く知られているのは、O(E + VlogV)を与えるフィボナッチヒープです。有向グラフの隣接リストを逆

+0

私は2つのリストを保持するのはどうですか?着信エッジリストと発信エッジリストは、これが良いアイデアのようですか? –

+0

@TimothyLeung:なぜか?私はそれがどのように出力エッジの1つのリストに対して何らかの利点を与えるかはわかりません。 – Beta

+0

@Betaグラフが密集しているのは、O(V^2)に過ぎないと思います。エッジを考慮しない。すべての頂点でO(1)の作業しか行わないので、O(V)です。したがって、複雑さの中でエッジが作用する必要があります。 – Dukeling

関連する問題