Графизация сериализации - PullRequest
       57

Графизация сериализации

41 голосов
/ 07 августа 2008

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

Ответы [ 4 ]

57 голосов
/ 07 августа 2008

Топологическая сортировка (из Википедии):

В теории графов топологическая сортировка или топологическое упорядочение направленного ациклический граф (ДАГ) является линейным упорядочение его узлов, в которых каждый узел предшествует всем узлам, к которым у него есть исходящие края. Каждый DAG имеет один или несколько топологических сортов.

Псевдокод:

L ← Empty list where we put the sorted elements
Q ← Set of all nodes with no incoming edges
while Q is non-empty do
    remove a node n from Q
    insert n into L
    for each node m with an edge e from n to m do
        remove edge e from the graph
        if m has no other incoming edges then
            insert m into Q
if graph has edges then
    output error message (graph has a cycle)
else 
    output message (proposed topologically sorted order: L)
1 голос
/ 23 января 2009

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

1 голос
/ 07 августа 2008

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

Пока это DAG, этот простой обход на основе стека должен быть тривиальным.

0 голосов
/ 07 августа 2008

Я придумал довольно наивный рекурсивный алгоритм (псевдокод):

Map<Object, List<Object>> source; // map of each object to its dependency list
List<Object> dest; // destination list

function resolve(a):
    if (dest.contains(a)) return;
    foreach (b in source[a]):
        resolve(b);
    dest.add(a);

foreach (a in source):
    resolve(a);

Самая большая проблема в этом состоит в том, что он не способен обнаруживать циклические зависимости - он может перейти в бесконечную рекурсию (т. Е. Переполнение стека ;-p). Единственный способ обойти это, что я могу увидеть, это перевернуть рекурсивный алгоритм в интерактивный с ручным стеком и вручную проверить стек на наличие повторяющихся элементов.

Кто-нибудь есть что-нибудь лучше?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...