您的位置:首页 > 编程语言 > Go语言

基于入度的拓扑排序(Kahn's Algorithm)

2016-05-11 20:25 375 查看
本文中的图用邻接链表来表示

拓扑排序只针对于有向无环图(DAG)才能完成,所以可以利用拓扑排序来判断一个有向图是否有环。

某一点的入度:图中指向该顶点的边的个数



图1 :DAG
以上图简单说明,点0的入度即为2。下面介绍拓扑排序的算法流程:
Step 1:计算出所有顶点的入度。
Step2 :将所有入度为0的点加入到一个队列。
Step3 :将队头元素取出,然后pop()。
   1.count变量表示访问过的顶点个数,将count加1.
       2.用top数组将每一次出队的元素保存起来。
          3.将这个点的所有相邻点的入度减一,如果某个相邻点的入度减小为0,则将这个相邻点加入到队列中。
Step4 :重复Step3直到队列为空
Step5 :如果count和顶点个数相同,则将top数组中的元素按序输出就是排序后的结果;如果count不等于顶点个数
     (在不相等的情况下,一般是count大于顶点个数),说明图中存在环,拓扑排序无法完成。

入度的计算方法:
遍历所有的顶点,每一次遍历,将该点所有相邻的点的入度都加1。所有的点遍历完后,入度就计算完成了。

具体拓扑排序代码如下:

#include
#include
#include
#include
using namespace std;

class Graph{
private:
int V;
list *adj;

public:
Graph(int V){
this->V =V;
adj = new list[V];
}
//有向图
void addEdge(int src, int dest){
adj[src].push_back(dest);

}

void toplogicSortInd(){

vector indegree(V,0);
queue q;
vectortop; //用来存储拓扑排序的结果
int count = 0;  //记录访问过的顶点个数
//step1:计算入度
for(int v = 0; v < V; v++){
list::iterator itr;
for(itr = adj[v].begin(); itr != adj[v].end(); itr++){
indegree[*itr]++;
}
}
//step2:将入度为0的点入队
for(int u = 0; u < V; u++){
if(indegree[u] == 0) q.push(u);
}
//step3 && step4
while(!q.empty()){
int v = q.front();
top.push_back(v);
q.pop();
count++;
list::iterator itr;
for(itr = adj[v].begin(); itr!=adj[v].end(); itr++){
if(--indegree[*itr] == 0)
q.push(*itr);
}

}
if(count != V){
cout << "\n图中存在环,拓扑排序无法完成。\n";
return;
}
else{
for(int i = 0; i < V; i++){
cout << top[i] << " ";
}
cout << endl;
}
}

};

// Driver program to test above functions
int main()
{
// Create a graph given in the above diagram
Graph g(6);
g.addEdge(5, 2);
g.addEdge(5, 0);
g.addEdge(4, 0);
g.addEdge(4, 1);
g.addEdge(2, 3);
g.addEdge(3, 1);

cout << "拓扑排序的一种结果是 \n";
g.toplogicSortInd();

return 0;
}


结果是:4 5 2 0 3 1

      
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  算法 c++ 拓扑排序