判断无向图是否有回路
1.初步认识
2.具体阐述
前提:对于无向图G,图中有结点数为m,边数为n
<1>.n>=m时,由图论知识可知有回路;
<2>.n<m时,若图中有度数小于2的结点,则删除这个结点及和它相连的边(0度结点只删结点自身);
<3>.重复执行<2>直到图中无结点或者没有度数小于2的结点停止;
<4>.判断,若此时图中无结点则原无向图G中无回路,若图中仍有结点存在则图中所有结点度数大于等于2,即图中总度数N>=2m,则图中剩下的的边数n>=m(因为一条边提供2个度数),由<1>得图中有回路;
3.理论证明
•证明:无向图中若边数大于等于结点数则图有回路(由已学的离散定理即可得出)
证:设无向图G = <V,E>,|V| = n,|E| = m,下列各命题是等价的:
G连通而不含回路(即G是树);
G中无回路,且m = n-1;
G是连通的,且m = n-1;
G中无回路,但在G中任二结点之间增加一条新边,就得到惟一的一条基本回路
4.算法描述
1.判断图中的结点数和边数
<1>若n>=m,则输出提示有回路,并返回;
<2>若n<m,继续往下执行;
2.结点入队
遍历每个结点,若度数为1或0则入队,并记录下入队元素个数;
3.删除结点和边
在队列不为空的情况下,队头元素出队
<1>若该结点度数为1,则置度数为-1,并且将与它相邻接的结点度数减1,同时判断减1后该邻接结点度数是否为1,若为1则入队,同时入队元素个数加1;
<2>若该结点度数为0,则直接置度数为-1;
4. 判断有无回路
<1>若入队元素个数小于结点总数,则有回路;
<2>否则,无回路;
5.算法实现
template<class T>
void MGraph<T>::JudgeCir()
{
int count=0;//记录入队结点个数
int Q[MaxSize];//队列
int front,rear,v;
front=rear=-1;
for(int i=0;i<vertexNum;++i)//初始化队列
{
cout<<"结点度数为:"<<adjlist[i].degree<<endl;
if((adjlist[i].degree==0)||(adjlist[i].degree==1)){//结点度数为或则入队
Q[++rear]=i;
count++;//记录入队元素个数
}
}
//执行删除(度为和的结点及连接的边)
while(front!=rear){
v=Q[++front];//队头元素出队
if(adjlist[v].degree==1){//度为的结点要删除边并且修改与边相连接的结点的度
adjlist[v].degree=-1;
for(int j=0;j<vertexNum;++j){
if(arc[v][j]==1){
adjlist[j].degree--;//该结点度数减
if(adjlist[j].degree==1){//入队(此结点之前度数大于,并未进入队中)
Q[++rear]=j;
count++;//记录入队元素个数
}
}
}
} else{//度为的结点直接标记度为-1
adjlist[v].degree=-1;
}
}
//判断有无回路
if(count<vertexNum){
cout<<"图中有回路"<<endl;
}else
cout<<"图中无回路"<<endl;
}
算法到此结束
6.算法分析
关键点1.构造函数
利用邻接矩阵构造图时,同时记录下每个结点的度数;
关键点2.判断有无回路
算法复杂度在O(n*n)左右判断无向图有无回路其实还有很多种方法…
PS:此方法是作者在数据结构课堂上由老师提问题而想出来的,又经过了两节课的思路完善,而后才去网上搜索了相关的资料,并且在网上发现了类似的思路,再次证实了作者的思路,但并没有抄袭。参考链接如下:
http://blog.csdn.net/lyflower/archive/2008/03/01/2137710.aspx lyflower专栏
再次感谢互联网资源的无私帮助
本文绝对原创,如需转载敬请声明
本文链接:http://www.cnblogs.com/jiayouchuang/archive/2010/05/20/1739978.html