Сериализация графа

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


person Kieron    schedule 07.08.2008    source источник


Ответы (4)


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

В теории графов топологическая сортировка или топологическое упорядочение ориентированного ациклического графа (DAG) - это линейное упорядочение его узлов, в котором каждый узел предшествует всем узлам, к которым он имеет исходящие ребра. Каждый 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)
person Andrew Peters    schedule 07.08.2008
comment
Эх ... скопировал прямо с википедии? - person Benjol; 06.10.2008
comment
Спасибо. Помог мне сопоставить тот факт, что дерево зависимостей можно отсортировать с помощью этого метода. :-) - person Shamasis Bhattacharya; 09.12.2013

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

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

person Lily Ballard    schedule 07.08.2008
comment
Да, вот как ты это делаешь. Это называется поиском в глубину (DFS). И если вы не уверены, что у вас есть DAG, вы должны проверять задние края, иначе цикл отправит вас в бесконечный цикл. - person sleske; 30.09.2009

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

person Community    schedule 23.01.2009
comment
Да, топологическая сортировка невозможна, если граф содержит циклы. Это соответствует реальному миру: если я попрошу вас сделать A перед B, и B перед A, вы не сможете меня удовлетворить ;-). - person sleske; 30.09.2009

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

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). Единственный способ обойти это, что я вижу, - это превратить рекурсивный алгоритм в интерактивный с ручным стеком и вручную проверить стек на наличие повторяющихся элементов.

У кого-нибудь есть что-нибудь получше?

person Kieron    schedule 07.08.2008
comment
вместо foreach используйте while, поддерживайте два указателя, просматривающих данные a: ведущий, который выполняет двойные шаги, а конечный, который выполняет одиночные шаги. Ведущий указатель обрабатывает фактические разрешения, и если он когда-либо переходит конечный указатель, возникает цикл. - person Tenderdude; 19.01.2017