Определение ацикличности графа для топологической сортировки

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

public static List<String> topologicalSort(Graph graph) {

    if(graph.getDirected() == false)
        throw new UnsupportedOperationException();

    Queue<Vertex> queue = new LinkedList<Vertex>();

    HashMap<String, Vertex> tempMap = graph.getVertices();
    for(Vertex vertex : tempMap.values()) {
        if(vertex.getInDegree() == 0)
            queue.add(vertex);
    }

    if(queue.isEmpty())
        throw new UnsupportedOperationException();

    ArrayList<String> returnList = new ArrayList<String>();
    while(!queue.isEmpty()) {
        Vertex tempVert = queue.poll();
        returnList.add(tempVert.getName());
        tempVert.setVisited(true);
        for(Edge edge : tempVert.getEdges()) {

           if(edge.getOtherVertex().getVisited() == true)
                throw new UnsupportedOperationException();
           edge.getOtherVertex().setVisited(true);
           edge.getOtherVertex().decInDegree();

           if(edge.getOtherVertex().getInDegree() == 0)
               queue.add(edge.getOtherVertex());
        }

    }

    return returnList;
}

person user3743340    schedule 02.07.2014    source источник
comment
Какой алгоритм? Вы не разместили код.   -  person Taylor    schedule 02.07.2014
comment
Просто пометьте каждый узел, который вы перебираете, как посещенный, и проверьте каждый новый узел, с которым вы имеете дело, если он уже был посещен, и если да - бросьте исключение.   -  person Nir Alfasi    schedule 02.07.2014
comment
Да, но если я выполняю итерацию и больше не могу продолжать, поскольку ни одна из вершин не имеет степени 0, это не вызовет исключения, а просто напечатает список короче ожидаемого возврата.   -  person user3743340    schedule 02.07.2014
comment
@ user3743340 это ваш ответ в вашем собственном комментарии список короче ...; короче списка вершин; см. ответ пользователя fabian ниже, который является правильным простым ответом, который вы ищете.   -  person necromancer    schedule 02.07.2014


Ответы (2)


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

Т.е. проверьте returnList.size() == graph.nodeCount() после цикла while (true означает ациклический ввод, false означает, что у ввода был цикл).

graph.nodeCount() должно быть количеством узлов в графе в начале метода.

person fabian    schedule 02.07.2014
comment
Кажется, это лучше, чем у меня :) Должно быть правильно. - person Pham Trung; 02.07.2014
comment
Идеально. Просто и именно то, что я искал. - person user3743340; 02.07.2014

Вы можете использовать Tarjan SCC, чтобы найти все компонент с сильной связью в ориентированном графе, если есть компонент с размером> 1 (более одного узла в этом компоненте), значит, существует цикл в этом компоненте.

Вы можете остановиться, как только алгоритм обнаружит сильно связанный компонент размером больше 1.

person Pham Trung    schedule 02.07.2014
comment
Я понимаю, что это сработает, но эффективность важна. Нет ли другого способа в текущей настройке моего кода, который позволил бы выполнить простую проверку? - person user3743340; 02.07.2014
comment
@ user3743340 взгляните на это - person Pham Trung; 02.07.2014