假设有向图采用邻接表存储,设计一个算法,判定
- 请概要说明你的算法思想。
- 编写你的算法,请在算法关键的地方给出必要的注释。
- 分析该算法的时间复杂度。
解答:
- 思路-用拓扑排序的方法来检查是否存在回路,具体步骤如下:
- 选择一个入度为 0 的未被访问的顶点
若找到,继续第(2)
若没找到,则图中有环,算法结束 - 将该顶点标记为已访问,并将其所有出边所指向的顶点的入度减一
- 回到第一步继续执行
- 选择一个入度为 0 的未被访问的顶点
- 伪代码如下
- 思路-用拓扑排序的方法来检查是否存在回路,具体步骤如下:
bool HasCirclePath( Graph &G) {
for (int i=0; i<G.VerticesNum(); i++) //初始化 Mark 数组
G.Mark[i]=0;
using std::stack;
Stack<int> S;
for(i=0;i<G.VerticesNum();i++){
if(!G.Indegree[i]) //度数为零的顶点入栈
S.push(i);
}
int count = 0; //已访问过的顶点数,排序开始前为 0
while( !S.empty() ) { //如果栈中还有图的顶点
int V = S.top();
S.pop();
count++; //已访问过的顶点数加一
G.Mark[V] = 1;
for( Edge e = G.FirstEdge(V); G.IsEdge(e); e= G.NextEdge(e) ){
//所有与之相邻的顶点入度减一
G.Indegree[G.ToVertex(e)]--;//边 e 的终点的入度值减一
if(!G.Indegree[G.toVertex(e)])
S.push(G.toVertex(e));//入度为零的点入栈
}
}
//若已访问的顶点个数小于图的顶点个数则为有环图,否则无环
return ( count<G.VerticesNum() );
}
(3)O(2|V|+|E|) 其中 V 为图的顶点数,E 为图的边数