/*
思想:利用拓扑排序来找图中的环,即离散数学中的w过程,
每次找到一条入度为零的边将其以及其所关联的边删除,
直到删除到环的时候再也进行不下去,此时将环中的任意
一个元素开始深度优先遍历即可。
*/
#include <iostream>
#include <queue>
using namespace std;
template<class EdgeType>
class Edge
{
public:
int start,end;//边的起始节点,终止节点
EdgeType weight;//边的权重(应该可以定义为int)
Edge()
{
start=0;
end=0;
weight=0;
}
Edge(int st,int en,int w)
{
start=st;
end=en;
weight=w;
}
bool operator > (Edge oneEdge)
{
if(weight>oneEdge.weight)
return true;
else
return false;
}
bool operator < (Edge oneEdge)
{
if(weight<oneEdge.weight)
return true;
else
return false;
}
};
template<class EdgeType>
class Graph
{
public:
int vertexNum; //图中节点个数
int edgeNum; //图中边的个数
int * Mark; //标记某节点是否被访问
Graph(int verNum)
{
this->vertexNum=verNum;
edgeNum=0;
Mark=new int[vertexNum];
for(int i=0;i<vertexNum;i++)
{
Mark[i]=0; //都没有被访问过
}
}
~Graph()
{
delete [] Mark;
}
//virtual Edge<EdgeType> FirstEdge(int oneVertex)=0;
//virtual Edge<EdgeType> NextEdge(Edge<EdgeType> oneEdge)=0;
int verticesNum()
{
return vertexNum;
}
int EdgesNum()
{
return edgeNum;
}
bool isEdge(Edge<EdgeType> oneEdge)
{
if(oneEdge.end>=0 && oneEdge.start>=0 && oneEdge.weight>0 && oneEdge.start!=oneEdge.end)//判断条件还不清楚
{
return true;
}
else
{
return false;
}
}
int startOfVertex(Edge<EdgeType> oneEdge)
{
return oneEdge.start;
}
int endOfVertex(Edge<EdgeType> oneEdge)
{
return oneEdge.end;
}
EdgeType weight(Edge<EdgeType> oneEdge) //返回oneEdge的权重
{
return oneEdge.weight;
}
//virtual void setEdge(int start,int end,int weight)=0;
//virtual void deleteEdge(int start,int end)=0;
};
template<class EdgeType>
class AdjGraph : public Graph<EdgeType >
{
private:
int ** matrix;
public:
AdjGraph(int verNum):Graph<EdgeType>(verNum)
{
matrix =new int * [verNum];
for(int i=0;i<verNum;i++)
{
matrix[i]=new int [verNum];
}
for(int i=0;i<verNum;i++)
for(int j=0;j<verNum;j++)
{
matrix[i][j]=999;
}
}
AdjGraph(int verNum,int ** a):Graph<EdgeType>(verNum)
{
matrix =new int * [verNum];
for(int i=0;i<verNum;i++)
{
matrix[i]=new int [verNum];
}
for(int i=0;i<verNum;i++)
for(int j=0;j<verNum;j++)
{
matrix[i][j]=a[i][j];
}
}
EdgeType getIJ(int i,int j)
{
if(i<this->vertexNum && i>=0 && j<this->vertexNum && j>=0)
return matrix[i][j];
else
{
cout<<"邻接矩阵越界"<<endl;
return 0;
}
}
int EdgesNum()
{
int edgeNum=0;
for(int i=0;i<this->vertexNum;i++)
{
for(int j=0;j<this->vertexNum;j++)
if(matrix[i][j]<999)
edgeNum++;
}
this->edgeNum=edgeNum;
return edgeNum;
}
void disp()
{
cout<<endl;
cout<<"此图的领接矩阵为"<<endl;
for(int i=0;i<this->vertexNum;i++)
{
for(int j=0;j<this->vertexNum;j++)
{
cout<<matrix[i][j]<<" ";
}
cout<<endl;
}
}
~AdjGraph()
{
for(int i=0;i<this->vertexNum;i++)
{
matrix[i]=new int [this->vertexNum];
}
delete [] matrix;
}
Edge<EdgeType> FirstEdge(int oneVer) //返回顶点的第一条边
{
Edge<EdgeType> tem;
tem.start=oneVer;
for(int i=0;i<this->vertexNum;i++)
{
if(matrix[oneVer][i]<999)
{
tem.end=i;
tem.weight=matrix[oneVer][i];
return tem;
//break;
}
}
tem.weight=-1;
tem.end=tem.start=0;
//cout<<"没有符合条件的边"<<endl;
return tem;
}
Edge<EdgeType> NextEdge(Edge<EdgeType> oneEdge)//返回与oneEdg有相同起点的下一条边
{
Edge<EdgeType> tem;
tem.start=oneEdge.start;
for(int i=oneEdge.end+1;i<this->vertexNum;i++)
{
if(matrix[oneEdge.start][i]<999)
{
tem.end=i;
tem.weight=matrix[oneEdge.start][i];
return tem;
}
}
tem.weight=-1;
//cout<<"没有符合条件的边"<<endl;
return tem;
}
void visit(int i)
{
cout<<i<<" ";
}
//深度优先搜索
void DFS(int i)//从i号节点开始深度优先搜索
{
this->Mark[i]=1;
//cout<<"zhe次从这里开始深度遍历"<<i<<endl;
visit(i);
for(Edge<EdgeType> e=FirstEdge(i);this->isEdge(e);e=NextEdge(e))
{
if(this->Mark[e.end]==0)
{
//cout<<"下次从这里开始深度遍历"<<e.end<<endl;
DFS(e.end);
}
}
}
void DFSGraph()//对图进行深度优先搜索
{
for(int i=0;i<this->vertexNum;i++)
this->Mark[i]=0; //标记都未访问
for(int i=0;i<this->vertexNum;i++)
{
if(this->Mark[i]==0)
{
DFS(i);
}
}
}
//广度优先搜索
void BFS(int i)//从i号节点开始广度优先搜索
{
queue<int> que;
que.push(i);
visit(i);
this->Mark[i]=1;
int p;
while(!que.empty())
{
p=que.front();
que.pop();
this->Mark[p]=1;
for(Edge<EdgeType> e=FirstEdge(p);this->isEdge(e);e=NextEdge(e))
{
if(this->Mark[e.end]==0)
{//此处要注意,在节点入队时候就要将Mark置为已访问,否则可能会导致同一节点多次入队
visit(e.end);
this->Mark[e.end]=1;
que.push(e.end);
}
}
}
}
void BFSGraph()//对图进行广度优先搜索
{
for(int i=0;i<this->vertexNum;i++)
this->Mark[i]=0; //标记都未访问
for(int i=0;i<this->vertexNum;i++)
{
if(this->Mark[i]==0)
{
BFS(i);
}
}
cout<<endl;
}
};
//拓扑排序,判断图中是否有环,并输出一个环
template<class EdgeType>
void TopuSortJudeIsExitCricle(AdjGraph<EdgeType>& G,int * SortArray)//从S出发生成最短路径
{
int n=G.verticesNum();
int * inderGree= new int [n];
for(int i=0;i<n;i++)
{
G.Mark[i]=0;
inderGree[i]=0;
SortArray[i]=-1;
}
for(int i=0;i<n;i++)
{
for(Edge<EdgeType> e = G.FirstEdge(i);G.isEdge(e);e=G.NextEdge(e))
{
//cout<<"e的开头"<<e.start<<endl;
//cout<<"e的结尾"<<e.end<<endl;
inderGree[e.end]++;
}
}
cout<<"inder数组"<<endl;
for(int j=0;j<n;j++)
{
cout<<inderGree[j]<<" ";
}
cout<<endl;
for(int i=0;i<n;i++)
{
int v;
for(v=0;v<n;v++)
{
if(inderGree[v]==0 && G.Mark[v]==0)
{
cout<<"入度为零的点为"<<v<<endl;
break;
}
}
if(v==n)
{
cout<<"图中存在环"<<endl;
cout<<"此时的mark数组"<<endl;
for(int j=0;j<n;j++)
{
cout<<G.Mark[j]<<" ";
}
cout<<endl;
for(int j=0;j<n;j++)
{
if(G.Mark[j]==0)
{
cout<<"环从这里开始"<<j<<endl;
G.DFS(j);
cout<<endl;
return;
}
}
}
G.Mark[v]=1;
SortArray[i]=v;
for(Edge<EdgeType> e = G.FirstEdge(v);G.isEdge(e);e=G.NextEdge(e))
{
inderGree[e.end]--;
}
}
delete [] inderGree;
}
int main()
{
//课本p170的图
int tem[6][6]={
{999, 1, 1, 1, 1, 1},
{999,999,1 ,999,999,999},
{999,999,999,999,1 ,999},
{999,999,1 ,999,999,999},
{999,999,999,1 ,999,999},
{999,999,999,999,1 ,999},
};
int n=6;
int ** a=new int *[n];
for(int i=0;i<n;i++)
{
a[i]=new int [n];
}
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
{
a[i][j]=tem[i][j];
}
AdjGraph<int> p(n,a);
p.disp();
cout<<"深度优先搜索"<<endl;
p.DFSGraph();
cout<<endl;
cout<<"广度优先搜索"<<endl;
p.BFSGraph();
int sortArray[n];
TopuSortJudeIsExitCricle(p,sortArray);
cout<<"拓扑序列为"<<endl;
for(int i=0;i<n;i++)
{
if(sortArray[i]>0)
cout<<sortArray[i]<<" ";
}
cout<<endl;
return 0;
}
大连理工大学软件学院数据结构第四章第九题
原创
©著作权归作者所有:来自51CTO博客作者DUT_LYH的原创作品,请联系作者获取转载授权,否则将追究法律责任
提问和评论都可以,用心的回复会被更多人看到
评论
发布评论
相关文章
-
大连理工大学——研究生学籍异动系统和离校系统使用简介
研究生学籍异动系统和离校系统使
杂谈 搜索 谷歌浏览器 移动端 -
数据结构-第四章 树
第四章:树
数据结构 b树 算法 二叉树 子树