好的,我必须对图进行拓扑排序算法。我需要找到度数为0的节点并将其排入队列,然后将其打印并删除去往它的所有边缘。我通过减少countList映射中进入边缘的数量来删除边缘。我将邻接列表作为地图,将每个节点的度数作为地图。我的算法仅访问邻接表的第一个元素。因此我的输出队列仅显示邻接列表的第一个关键字。一遍又一遍。我在25处停止了while循环,因此它不会是无限的。

            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-> first)-;

在将顶点推入队列后。因此,应该将该顶点的计数减为-1。
这使我的输出范围大大缩小。

现在就可以了!!!
我将while循环更改为在队列为空后停止,并在while循环中打印了队列,从而解决了该问题。

我的输出现在是:

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


好的,仅当节点名称仅为单个值时,此代码才有效。
如何更改节点名称长于单个字符的值的adjList映射?
也许键值指向一个链表?如果是这样,我该怎么做?

最佳答案

好吧,现在我们到了某个地方。

第一个版本(在您进行编辑之前)确实错误地减少了传入的边缘计数。

现在还有另一个问题:在每次迭代中,您都重复获取已经被占用的节点(节点#1是一个很好的示例),因为它们的计数仍然为零(传入边的数量)。通过一次又一次地减少其祖先,某些计数将降至零以下(例如对于节点2)。

您必须以某种方式标记已使用的节点,并且不要在每个周期中一次又一次地使用它们。这可以通过以下方法实现:a)通过为节点设置一些标志,b)使用一组使用的节点,c)通过从列表中删除该节点,或者(可能是最简单的)d)通过将其边缘计数设置为负数来实现将它们放入输出队列后的数字(例如-1)。

在您进行第二次编辑后,这样的算法应该可以工作(在短短的两周后对我有效)。但是,adjList的用法很奇怪-您如何在一个映射中准确地包含一个节点的多个边?

关于c++ - 拓扑排序算法无法正常工作,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22920925/

10-13 06:28