2009-05-10 4 views
1

Может ли кто-нибудь помочь мне быстрее реализовать j2ME алгоритм Dijkstra? У меня две петли, одна внутри. Как этоСамый быстрый алгоритм Дейкстры для 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. Убедитесь, что внутренний цикл не учитывает посещенные узлы. Все мои посещенные узлы находятся в конце массива, и я узел знаю счет. Поэтому я могу легко пропустить их вообще.

ответ

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

Я назвал этот алгоритм. Я нашел более простой алгоритм в другом месте. Обратите внимание, что если бы мне пришлось внедрить тот, который был в Википедии, есть два внутренних цикла. , а Q не пуст: // Внешняя петля. u: = вершина в Q с наименьшим dist []; // Первый внутренний цикл. .... для каждого соседа v из u: // Второй внутренний цикл. Вторая внутренняя петля меньше. Он может выполнять максимум 4-5, поскольку для каждого узла должно быть не более 5 ребер. Число узлов, имеющих более 2 ребер, составляет 1000 из 23000 общих узлов. Таким образом, время выполнения для внутреннего цикла пренебрежимо мало. – dmantamp

+0

Вы читали раздел в википедии о времени работы? Он предлагает использовать списки смежности и двоичную кучу или какую-либо другую структуру в качестве очереди приоритетов - это в значительной степени удалит этот первый внутренний цикл –

+0

. Присмотритесь внимательно, Deekshit - если вы используете приоритетную очередь (кучу) для Q, находите наименьший элемент в Q равен O (1), что делает общее время выполнения O (n + m) числом узлов и ребер. –

1

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

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, я должен сделать это, чтобы взять как можно меньше места.

+0

Это пренебрежимо мало? Профилировали ли вы его и протестировали?Псевдокод выше * - это алгоритм Дейкстры, поэтому нет; требуется внутренний цикл. Ваш алгоритм почти почти O (V^2), как сказал Роман, но если вы правильно реализуете алгоритм, без предположений или преждевременных оптимизаций, вы получите правильную сложность O(). – GManNickG

+0

Да, я это сделал. Максимальное количество раз. Первое выполнение внутреннего цикла для каждой итерации внешнего цикла составляет 23000 (количество нот). Но второй внутренний цикл выполняется всего 5 раз (максимальное количество ребер для каждого узла). Рассмотрим мой пример, когда у меня есть 25000 узлов. И я нахожу кратчайший путь в 1000-й итерации. Таким образом, второй внутренний цикл выполняет минимум 24000 для каждой итерации внешнего цикла. Это 1000 * 25000. Но второй внутренний цикл занимает всего 5 итераций. Это 1000 * 5 (макс.). Таким образом, только узким местом является первый внутренний цикл. – dmantamp

+0

Когда я тестировал второй цикл, он не потребляет 2-3 секунды времени выполнения. Но первый цикл действительно тяжелый. Я попытался сократить время наполовину, сохранив второе минимальное расстояние. Это сократило 30% времени выполнения. Но увеличил сложность кода. BTW, программа не занимает больше двух секунд на моем настольном ПК. Это займет почти 5 минут на моем мобильном устройстве или эмуляторе. – dmantamp

Смежные вопросы