2009-05-10 9 views
1

誰でも私がDijkstraアルゴリズムのj2ME実装を高速化するのを助けることができますか?私は2つのループを持っています。私はほとんど23000ノードとそれらを接続50000のエッジを有するこの最も速いDijkstraアルゴリズムfor j2ME

while(for each item in Q) 
{ 
    //...do something. 

    //the following loop is to find the minimum 
    for(all un-visited nodes in Q) 
    { 
     //.. do something to get min. 
    } 
} 

よう...インナーループは、以下に言及される全ての改良後169330131回の平均を実行します。これは私のw910i携帯電話では5分、エミュレータでは数分以上かかる。これは私のためにあまりにも多く見えます。改善のための提案はありますか?私はすでに以下の改善が行われています。

  1. ベクトルの代わりに配列を使用します。
  2. 内部ループが訪問先ノードを考慮していないことを確認してください。訪問したすべてのノードは配列の最後にあり、Iノードはカウントを知っています。だから、私は簡単にそれらをすべてスキップすることができます。

答えて

1

実装に問題があります。複雑さはO(E + V * log2(V))です。

これは、50000 + 23000 *〜15 = 400 000回の繰り返しを意味します。

あなたの現在の複雑さはほぼO(V^2)です。

2

私はあなたのアルゴリズムが問題だと思います。内側のループは、外側のループ内の項目の各未訪問の隣人を見てする必要があります。

for each (item in Q) 
{ 
    for each (unvisited neighbour of item) 
    { 
    } 
} 

pseudocode implementation in wikipediaと比較:

1 function Dijkstra(Graph, source): 
2  for each vertex v in Graph:   // Initializations 
3   dist[v] := infinity    // Unknown distance function from source to v 
4   previous[v] := undefined   // Previous node in optimal path from source 
5  dist[source] := 0      // Distance from source to source 
6  Q := the set of all nodes in Graph 
     // All nodes in the graph are unoptimized - thus are in Q 
7  while Q is not empty:     // The main loop 
8   u := vertex in Q with smallest dist[] 
9   if dist[u] = infinity: 
10    break       // all remaining vertices are inaccessible 
11   remove u from Q 
12   for each neighbor v of u:   // where v has not yet been removed from Q. 
13    alt := dist[u] + dist_between(u, v) 
14    if alt < dist[v]:    // Relax (u,v,a) 
15     dist[v] := alt 
16     previous[v] := u 
17  return previous[] 
+0

私はこのアルゴリズムを参照しました。私はもっ​​と簡単なアルゴリズムを見つけました。 Wikipediaで実装しなければならない場合、内部ループは2つあります。 Qは空ではありません。//外側ループ。 u:最小のdist [];を持つQの頂点//最初の内部ループ。 .... u://の2番目の内側ループの各近隣ループ。 2番目の内側ループが小さくなります。各ノードに対して最大5つのエッジが存在するため、最大4〜5回実行される可能性があります。エッジが2つ以上あるノードの数は、23000個のノードのうち1000個です。したがって、内部ループの実行時間は無視できます。 – dmantamp

+0

実行時間についてのウィキペディアのセクションを読んだことがありますか?隣接リストとバイナリヒープまたはその他の構造体を優先キューとして使用することをお勧めします。これにより、最初の内部ループが大幅に削除されます –

+0

Deekshit - Qの優先順位キュー(ヒープ)を使用すると、 Qの最小要素はO(1)であり、ノードとエッジの数でランタイムO(n + m)を合計します。 –

1

私はこのアルゴリズムを言及しました。もっと単純なアルゴリズムが見つかった。 Wikipediaで実装しなければならない場合、内部ループは2つあります。

while Q is not empty: //Outer loop. 
    u := vertex in Q with smallest dist[];// First inner loop. 
    .... 
    for each neighbor v of u: //Second inner loop. 

2番目の内側ループが小さくなります。各ノードに対して最大5つのエッジが存在するため、最大4〜5回実行される可能性があります。エッジが2つ以上あるノードの数は、23000個のノードのうち1000個です。したがって、内部ループの実行時間は無視できます。最初の内側ループが問題です。最小のノードを見つける。これをj2MEデバイスで実行する必要があるため、できるだけスペースを少なくする必要があります。

+0

それはごくわずかですか?プロファイルしてテストしましたか?上記の疑似コードは* Dijkstraのアルゴリズムなので、そうではありません。内側のループが必要です。あなたのアルゴリズムはほぼO(V^2)に近いですが、アルゴリズムを正しく、仮説や早期最適化なしで実装すると、正しいO()複雑さが得られます。 – GManNickG

+0

はい私はしました。アウターループ実行の繰り返しごとの最初の内部ループ実行回数は23000(ノート数)です。しかし、2番目の内部ループは5回だけ実行されます(各ノードの最大エッジ数)。 25000個のノードがある私の例を考えてみましょう。そして、私は1000回目の反復で最短経路を見つけました。したがって、2番目の内側ループは、外側ループの反復ごとに最低24000を実行します。それは1000 * 25000です。しかし、2番目の内部ループは5回の反復しか必要としません。それは1000 * 5(最大)です。ボトルネックだけが最初の内側ループです。 – dmantamp

+0

2番目のループをテストしたところ、2〜3秒の実行時間はほとんどかかりませんでした。しかし、最初のループは本当に重いです。 2番目の最小距離を保存することで時間を半分に減らそうとしました。これにより、実行時間が30%短縮されました。しかし、コードの複雑さが増しました。ところで、プログラムは私のデスクトップPCで2秒以上かかることはありません。私の携帯電話やエミュレータでは約5分かかります。 – dmantamp

関連する問題