У меня есть несколько комментариев к коду:
1) Взять те строки в первом фрагменте кода:
while(st.hasMoreTokens()){
String currentToken = st.nextToken();
if(!cityList.contains(currentToken.trim())){
cityList.add(currentToken.trim());
}//if
}//while hasMoreTokens
Метод cityList.contains()
использует линейное время для числа городов, и while(st.hasMoreTokens())
может выполняться O(V^2)
раз, где V - число вершин, поскольку вы можете иметь плотный граф. Итак, только в этом одном цикле вы потребляете O (V ^ 3) времени, которое уже хуже, чем DFS (O(V + E)
, что составляет O(V^2)
в плотном графе). Вы не можете ускорить цикл O (V ^ 2), потому что вам нужно прочитать все границы, но вы можете использовать более эффективную структуру данных для хранения этого списка городов, а именно хеш (O(1)
lookup, O(1)
вставки).
2) Во втором фрагменте кода:
while(st.hasMoreTokens()){
String firstToken = st.nextToken().trim();
String secondToken = st.nextToken().trim();
cityGraph[cityList.indexOf(firstToken)][cityList.indexOf(secondToken)] = 1;
cityGraph[cityList.indexOf(secondToken)][cityList.indexOf(firstToken)] = 1;
}//while hasMoreTokens
Точно так же. Используйте хеш вместо списка.
3) Внутренняя петля вашего DFS
if(cityGraph[startNode][i] == 1){
if( i == city2 ){
System.out.println("yes");
return;
}//if city2 found
q.add(i);
cityGraph[startNode][i] = 0; //Set to visited
}//if vertex exist
Есть две проблемы. Во-первых, вы перезаписываете представление графа каждый раз, когда запускаете DFS. Установив cityGraph[startNode][i] = 0;
, вы фактически удаляете край вашего графика. Если вы восстанавливаете график для каждой DFS, это огромная проблема.
Вторая проблема заключается в том, что мне кажется, что вы отмечаете посещенные узлы неправильно. Вы просто отмечаете посещенные EDGES, а не узлы. Если у вас есть путь 1 -> 2 и путь 1 -> 4 -> 2, вы собираетесь посетить (и добавить в очередь) узел 2 два раза.
Чтобы решить обе проблемы, используйте массив boolean visited[#cities]
. Каждый раз, когда вы запускаете DFS, вы устанавливаете все узлы как не посещенные. Каждый раз, когда вы проверяете ребро, вы проверяете, уже посещали ли вы этот узел. Если нет, добавьте его в очередь.
На последней ноте
q.remove();//remove the top element and start with new node
if(!q.isEmpty()){
startNode = (Integer) q.element();
}//if
Это ужасно, так как вы уже проверяете, пуста ли очередь в цикле while. Вместо этого вы можете просто переместить этот код в начало цикла while, удалив условие if (поскольку вы знаете, что очередь не пуста):
while(!q.isEmpty()){
startNode = (Integer) q.element();
q.remove();
Надеюсь, это поможет ....