Найдите острова в ориентированном графе

Я работаю на непонятном языке с плохим управлением зависимостями. Чтобы помочь кодовой базе из 14000 файлов, я написал несколько инструментов для синтаксического анализа (на Java) и сгенерировал граф зависимостей.

Я написал свой собственный график и классы BFS, и они прекрасно работают. С ними у меня такие методы как getParents() и getChildren().

Теперь я пытаюсь найти «острова» на этом графике; то есть я пытаюсь найти, какие разделы нашей кодовой базы не зависят друг от друга, в надежде собрать их в изолированные модули.

Позже я также планирую проанализировать отдельные острова, чтобы увидеть, есть ли в них какие-либо слабые места, где мы можем установить модульный барьер и определить интерфейс этого модуля, но это будет позже.

Вот сейчас думаю сделать так:

Map<DependencyEntry, Set<DependencyEntry>> allChildren = new ...;
for(DependencyEntry entry : allFiles) allChildren.put(entry,getAllChildren(entry));
Set<DependencyEntry> visited = new ...;
Set<DependencyEntry> largest = new HashSet<DependencyEntry>(); // size 0
// slightly more expensive but more readable
for(DependencyEntry entry : allChildren.keySet()) {
    Set<DependencyEntry> set = allChildren.get(key);
    if(set.size() > largest.size()) largest = set;
}
visited.addAll(largest);

Это должно дать мне самый большой остров. Оттуда я могу просмотреть и исключить любые наборы, содержащие какие-либо посещенные узлы, а затем запустить его снова, чтобы получить следующий по величине остров, и так далее.

Это точный алгоритм? Есть ли лучший способ решить эту проблему, которого я не вижу?


person corsiKa    schedule 25.08.2011    source источник
comment
Интересный вопрос, освежающий переход от вопросов о том, как сделать XX на языке YY, или о помощи с кодом ошибки 0x34!   -  person GBa    schedule 25.08.2011


Ответы (2)


Похоже, вы хотите создать набор подключенных компонентов, найденных в графе зависимостей. Оттуда вы можете перебрать коллекцию и определить самый большой компонент (или любую другую интересную метрику).

person PaulF    schedule 25.08.2011

было бы проще использовать графическую библиотеку, потому что такие вещи встроены. обычно они позволяют хранить произвольную информацию в узлах, ребрах, поэтому вы по-прежнему можете использовать свои собственные классы для данных, но библиотека предоставляет поддержку и стандартные алгоритмы.

алгоритм, который вы описываете, кажется немного неясным в отношении того, что такое корневые узлы. если вы не начнете с корня, вы не найдете «весь остров» — только части ниже (дочерние элементы), с которых вы начали. вы можете исправить это, следуя родителям, а также детям. кроме того, это звучит нормально - насколько я могу судить, он делает то, что говорит ответ Пола, и находит подключенные компоненты.

см. также Хорошая библиотека графических алгоритмов Java?

person andrew cooke    schedule 25.08.2011