什么是拓扑排序呢?就是将一个有向无环图中所有顶点在不违反先决条件关系的前提下排成线性序列的过程称为拓扑排序。
学拓扑排序有什么用呢?当然有用啦~。比如说学校排课的时候,会考虑到有的课程需要先修。我们学完C程序设计这门课,有了编程基础,然后才能学习数据结构。大学要修很多门课程的,人为的去排课很头痛的,这时候就可以用拓扑排序解决这个问题。
拓扑排序只针对有向无环图(DAG),有两种方法可以实现,一种是队列实现,另外一种是深搜(DFS)实现。
这里先介绍队列实现的方法。
(1)从图中选择任意一个入度为0的顶点且输出
(2)从图中删掉此顶点及所有的出边,将其入度减少1
(3)回到第(1)步继续执行
我们对上面图进行拓扑排序,我这里采用的是邻接表储存图,贴代码。
#include<vector>
#include<iostream>
#include<queue>
using namespace std;
class Graph
{
int v;
vector<int> *adj;
int *indegree;
public:
Graph(int n);
~Graph();
void addEdge(int start,int end);
void TopsortbyQueue();
};
Graph::Graph(int n)
{
v=n;
adj=new vector<int>[n];
indegree=new int[n];
for(int i=0;i<n;i++)
indegree[i]=0;
}
Graph::~Graph()
{
delete [] adj;
delete [] indegree;
}
void Graph::addEdge(int s,int e)
{
adj[s].push_back(e);
indegree[e]++;
}
void Graph::TopsortbyQueue()
{
queue<int> aqueue;
int count = 0;
for(int i=0;i<v;i++)
{
if(indegree[i]==0)
aqueue.push(i);
}
while(!aqueue.empty())
{
int node = aqueue.front();
aqueue.pop();
cout<<node<<" ";
count++;
for(vector<int>::iterator ii=adj[node].begin();ii!=adj[node].end();ii++)
{
indegree[*ii]--;
if(indegree[*ii]==0)
aqueue.push(*ii);
}
}
if(count<v)
cout<<"有环"<<endl;
}
int main()
{
Graph g(9);
g.addEdge(0,2);
g.addEdge(0,7);
g.addEdge(1,2);
g.addEdge(1,4);
g.addEdge(1,3);
g.addEdge(2,3);
g.addEdge(3,5);
g.addEdge(3,6);
g.addEdge(4,5);
g.addEdge(7,8);
g.addEdge(8,6);
g.TopsortbyQueue();
return 0;
}
运行结果
图的每条边处理一次,图的每个顶点访问一次,采用邻接表表示时时间复杂度为 O(n+e)。采用相邻矩阵表示时,为O(n*n)。
对DFS实现拓扑排序有兴趣的,点击:拓扑排序DFS版
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)