6.4.3 拓扑排序
在AOV网中,不应该出现有向环路,因为有环意味着某项活动以自己作为先决条件,这样就进入了死循环。
检测的办法是对有向图进行拓扑排序(Topological Sort),若网中所有顶点都在它的拓扑有序序列中,则AOV网中必定不存在环。
下面是拓扑排序算法的描述:
(1)在有向图中选择一个入度为0的顶点(即没有前驱的顶点),由于该顶点没有任何先决条件,输出该顶点;
(2)从图中删除所有以它为尾的弧;
(3)重复执行(1)和(2),直到找不到入度为0的顶点,拓扑排序完成。
如果图中仍有顶点存在,却没有入度为0的顶点,说明AOV网中有环路,否则没有环路。
拓扑排序示例:
根据邻接链表存储结构实现拓扑排序:(邻接链表的实现在前面的博客)
public void TopologicalSort(GraphAdjList<T> graph)
{
bool[] marker = new bool[graph.NodeNum];
int outputNodeNum = 0;
while (outputNodeNum < graph.NodeNum)
{
bool[] currentMarker = new bool[graph.NodeNum];
for (int i = 0; i < graph.NodeNum; i++)
{
if (marker[i] == true)
continue;
AdjListNode<T> adjNode = vexList[i].FirstAdj;
while (adjNode != null)
{
currentMarker[adjNode.AdjVexIndex] = true;
adjNode = adjNode.Next;
}
}
bool ifHasCycle = true;
for (int i = 0; i < graph.NodeNum; i++)
{
if (marker[i] == false && currentMarker[i] == false)
{
marker[i] = true;
outputNodeNum += 1;
Console.WriteLine(graph.vexList[i].Node.Value);
ifHasCycle = false;
}
}
if (ifHasCycle)
{
Console.WriteLine("The graph has cycle...");
break;
}
}
}
调用代码:
GraphAdjList<int> adjList = new GraphAdjList<int>(100);
//Inial graph object
GraphNode<int> node1 = new GraphNode<int>(1);
GraphNode<int> node2 = new GraphNode<int>(2);
GraphNode<int> node3 = new GraphNode<int>(3);
GraphNode<int> node4 = new GraphNode<int>(4);
GraphNode<int> node5 = new GraphNode<int>(5);
GraphNode<int> node6 = new GraphNode<int>(6);
adjList.SetNode(node1);
adjList.SetNode(node2);
adjList.SetNode(node3);
adjList.SetNode(node4);
adjList.SetNode(node5);
adjList.SetNode(node6);
adjList.SetEdge(0, node1, node2, 1);
adjList.SetEdge(3, node1, node4, 3);
adjList.SetEdge(4, node2, node6, 12);
adjList.SetEdge(7, node3, node1, 2);
adjList.SetEdge(8, node3, node4, 1);
adjList.SetEdge(9, node4, node5, 1);
adjList.SetEdge(12, node5, node2, 3);
adjList.SetEdge(13, node5, node6, 2);
adjList.TopologicalSort(adjList);
System.Console.ReadKey();
输出结果:
3
1
4
5
2
6