Самый быстрый алгоритм Дейкстры для j2ME - PullRequest
1 голос
/ 10 мая 2009

Может кто-нибудь помочь мне ускорить реализацию алгоритма Дейкстры в 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.
    }
}

У меня почти 23000 узлов и 50000 ребер, соединяющих их ... Внутренний цикл выполняется в среднем 169330131 раз после всех улучшений, упомянутых ниже. Это займет 5 минут на моем мобильном устройстве w910i и больше, чем на моем эмуляторе. Это выглядит слишком много для меня. Есть предложения по улучшению? У меня уже есть следующие улучшения.

  1. Использование массива вместо вектора.
  2. Убедитесь, что внутренний цикл не учитывает посещенные узлы. Все мои посещенные узлы находятся в конце массива, и я знаю количество узлов. Так что я могу легко их пропустить.

Ответы [ 3 ]

2 голосов
/ 10 мая 2009

Я думаю, что ваш алгоритм в вопросе неверен. Внутренний цикл должен смотреть на каждого невидимого соседа элемента во внешнем цикле:

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

Сравните это с реализацией псевдокода в википедии :

 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[]
1 голос
/ 10 мая 2009

Я ссылался на этот алгоритм. Я нашел более простой алгоритм в другом месте. Обратите внимание, что если бы мне пришлось реализовать один в Википедии, есть две внутренние петли.

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. 

Второй внутренний цикл меньше. Может выполняться максимум 4-5, так как для каждого узла не более 5 ребер. Количество узлов, имеющих более 2 ребер, составляет 1000 из 23000 общих узлов. Таким образом, время выполнения внутреннего цикла незначительно. Первый внутренний цикл - это проблема. Нахождение наименьшего узла. Поскольку я должен выполнить это на устройстве j2ME, я должен сделать так, чтобы он занимал как можно меньше места.

1 голос
/ 10 мая 2009

Что-то не так с вашей реализацией. Это сложность O (E + V * log2 (V)).

Это означает, что 50000 + 23000 * ~ 15 = 400 000 итераций.

Ваша текущая сложность почти равна O (V ^ 2).

...