Алгоритм топологической сортировки не работает правильно

0

Хорошо, мне нужно сделать топологический алгоритм сортировки на графике. Мне нужно найти узел с степенью 0 и поставить его в очередь, затем распечатать его и удалить все ребра, идущие к нему. Я удаляю ребра, уменьшая количество ребер, попадающих в него на карте countList. У меня есть список смежности в виде карты, а число в градусах для каждого узла - как карта. Мой алгоритм получает доступ только к первому элементу списка смежности. поэтому моя очередь вывода отображает только первый ключ карты списка смежности. вновь и вновь. Я остановил цикл while на 25, чтобы он не был бесконечным.

            string z = "";
            string a = "";
            cout << "Queue: ";
            do{
                for(it = countList.begin(); it!=countList.end(); ++it){
                    if(it->second == 0){
                        Q.push(it->first);
                                                    countList.at(it->first)--;
                        z = adjList[it->first];
                        cout <<"z: " << z <<endl;
                        //remove edges
                        for(int i = 0; i< z.length(); i++){
                            a = z.at(i);
                            cout << "z at " <<i << " : " <<a <<endl;
                            countList.at(a)--;
                        }//end for
                    }//end if
                    //cout << Q.front() << ", ";
                    //Q.pop();

                }//end for
                cout << Q.front() << ", ";
                Q.pop();
            }while(!Q.empty());

Может ли кто-нибудь помочь мне понять, почему он не выполняет итерацию через countList и остается только на первом элементе?

Спасибо.

Поэтому я изменил countList.at(a) -+1, на countList.at(a) - для правильного декрементации. Теперь результат больше, чем только первая вершина, равная 0 в градусах. Но выход по-прежнему не так.

Вот и все. Мои объявления переменных

    vector<string> E;   
map<string, string> adjList;
map<string, int>countList;
map<string, int>::iterator it;
queue<string> Q;

Я не хочу выставлять код для adjacencyList или countList, но вот как они выглядят.

//These represent the edges between the two paired nodes
AdjacencyList: (1,2) (1,4) (1,3) (2,4) (2,5) (3,6) (4,6) (4,7) (4,3) (5,4) (5,7) (7,6)

//The first is the node name and the second element is how many edges come into that node.
countList: (1,0) (2,1) (3,2) (4,3) (5,1) (6,3) (7,2)

Мой вывод должен быть:

Queue: 1,2,5,4,3,7,6 
//or
Queue: 1,2,5,4,7,3,6

ОК, я добавил

countList.at(it-> первый) -;

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

ОК, ЭТО РАБОТАЕТ СЕЙЧАС !!! Я изменил цикл while, чтобы остановиться после того, как очередь пуста и напечатала очередь в цикле while, и устранила проблему.

Теперь мой вывод:

Queue: 1, 2, 5, 4, 7, 3, 6, 

Хорошо, этот код будет работать, только если имена узлов являются только одиночными. Как изменить отображение adjList для значений, имена узлов которых длиннее одного символа? Возможно, связанный список указывает на ключевое значение? И если да, то как мне это сделать?

  • 0
    Если вам не гарантированно иметь только один узел со степенью 0 (чего у вас нет в общем случае), я думаю, что ваш базовый подход ошибочен. Если у вас есть набор отношений { (a,b), (c,b) } , a и c имеют степень 0, но вы не можете обработать потомков любого из них, пока не обработаете оба из них (правильный порядок будет a, c, b или c, a, b ) ...
  • 0
    Я не знаю, если это для изучения, но существуют алгоритмы для этого. boost.org/doc/libs/1_42_0/libs/graph/doc/topological_sort.html
Показать ещё 2 комментария
Теги:
loops
sorting
graph
topological-sort

1 ответ

0
Лучший ответ

Хорошо, теперь мы куда-то добираемся.

Самая первая версия (до вашего редактирования) неправильно уменьшала количество входящих фронтов.

Теперь есть еще одна проблема: на каждой итерации вы повторно берете узлы, которые уже были взяты (пример # 1 - хороший пример), потому что они все еще имеют нулевой счет (количество входящих ребер). Уменьшая число своих предков снова и снова, некоторые из них упадут ниже нуля (например, для узла № 2).

Вы должны как-то пометить узлы, которые уже были использованы, и не использовать их снова и снова в каждом цикле. Это может быть достигнуто: a) путем установки некоторого флага для узла, b) с использованием набора используемых узлов, c) путем удаления узла из списка или (возможно, самого простого) d) путем установки их количества краев на отрицательный номер (например, -1) после помещения их в очередь вывода.

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

  • 0
    Я использовал строковую карту. Где значение ключа - это имя узла, а второе строковое значение - это объединенная строка ребра. А затем я разделил строку для имен других узлов. Это будет работать, только если имена узлов имеют одно значение. Я только что понял это. Итак, как бы я их отобразил, если имена узлов больше, чем одно значение? Могу ли я иметь связанный список как сопоставленное значение ключа? Это будет выглядеть так (1, 234)
  • 0
    Да, вы можете сделать это. Или вы можете использовать мультикарту.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню