求图的简单路径和回路

下面是用邻接表存储无向图,然后输出图中指定顶点间的指定长度的简单路径,简单路径就是路径中的顶点不重复,还有一个就是求出图中经过某顶点的回路,都是对图的遍历算法的应用,主要是深度优先的遍历,加上简单的回溯。

下面是代码:
//文件"graph.h" #include <iostream> #include <string> #include <queue> using namespace std; bool visited[20]; int path[20]; struct ArcNode { int adjvex; ArcNode *nextarc; }; struct VexNode { string data; ArcNode *firstarc; }; class NDGraph { private: VexNode vertices[20]; int vexnum; int arcnum; public: NDGraph() { vexnum=0; arcnum=0; } int GetVexNum() { return vexnum; } int Locate_Vex(string v) { for(int i=0;i<vexnum;i++) if(vertices[i].data == v) return i; return -1; } void Create_NDGraph() { //构造无向图 string v1,v2; int i,j,k; cout<<"输入顶点数和边数:"; cin>>vexnum>>arcnum; while(vexnum>20) { cout<<"请输入少于20个顶点(重新输入顶点数和边数):"; cin>>vexnum>>arcnum; } cout<<"输入顶点名称:"; for(i=0;i<vexnum;i++) { cin>>vertices[i].data; vertices[i].firstarc=NULL; } for(k=0;k<arcnum;k++) { cout<<"输入每条边对应的两个顶点:"; cin>>v1>>v2; i=Locate_Vex(v1); j=Locate_Vex(v2); while(i == -1 || j == -1) { cout<<"顶点中有不符合要求的,请重新输入:"; cin>>v1>>v2; i=Locate_Vex(v1); j=Locate_Vex(v2); } ArcNode *p=new ArcNode; p->adjvex=j; p->nextarc=vertices[i].firstarc; vertices[i].firstarc=p; //置对称边 ArcNode *q=new ArcNode; q->adjvex=i; q->nextarc=vertices[j].firstarc; vertices[j].firstarc=q; } cout<<"无向图构造完成"<<endl; } void DFS_Traverse() { for(int i=0;i<vexnum;i++) visited[i]=false; for(i=0;i<vexnum;i++) if(!visited[i]) DFS(i); } void DFS(int v) { visited[v]=true; cout<<vertices[v].data<<" "; ArcNode *p; int w; for(p=vertices[v].firstarc;p;p=p->nextarc) { w=p->adjvex; if(!visited[w]) DFS(w); } } void BFS_Traverse() { for(int i=0;i<vexnum;i++) visited[i]=false; for(i=0;i<vexnum;i++) if(!visited[i]) BFS(i); } void BFS(int v) { visited[v]=true; cout<<vertices[v].data<<" "; queue<int> qu; int w,k; ArcNode *p=NULL; qu.push(v); while(!qu.empty()) { w=qu.front(); qu.pop(); for(p=vertices[w].firstarc;p;p=p->nextarc) { k=p->adjvex; if(!visited[k]) { visited[k]=true; cout<<vertices[k].data<<" "; qu.push(k); } } } } void Print_X_Y_Path(int u,int v,int l,int d) { //求出一条长度为l的从u到v的路径,d刚进来的时候是-1 int m; d++; visited[u]=true; path[d]=u; if(u == v && d == l) //找到一条路径 { for(int i=0;i<l;i++) cout<<vertices[ path[i] ].data<<"-->"; cout<<vertices[ path[i] ].data<<endl; } else if(u == v && d!=l) { //出现这种情况直接回溯上一顶点,不浪费时间去DFS goto loop; } else { ArcNode *p=vertices[u].firstarc; //继续DFS while(p) { m=p->adjvex; if(!visited[m]) Print_X_Y_Path(m,v,l,d); p=p->nextarc; } } //恢复环境,使顶点可重新使用 //路径长度减一 loop: visited[u]=false; d--; } void Print_X_X_Path(int i,int j,int d) { //找出从i到i的回路,思想和上面的类似 int v,k; ArcNode *p; visited[i]=true; d++; path[d]=i; if(i == j && d>2) { for(k=0;k<d;k++) cout<<vertices[ path[k] ].data<<"-->"; cout<<vertices[ path[k] ].data<<endl; } else if(i == j && d==2) //一条边只可以走一次 goto lop; else { p=vertices[i].firstarc; while(p) { v=p->adjvex; if(!visited[v] || v == j) Print_X_X_Path(v,j,d); p=p->nextarc; } } lop: visited[i]=false; d--; } };

主函数文件

#include "graph.h" #include <iostream> #include <string> using namespace std; int main() { NDGraph G; string v1,v2; int u,v; int num; G.Create_NDGraph(); cout<<"图的深度优先遍历为:"; G.DFS_Traverse(); cout<<endl; cout<<"图的广度优先遍历为:"; G.BFS_Traverse(); cout<<endl; cout<<"输入两个顶点名称和一个数字,"<<endl; cout<<"将输出长度为输入数字大小的两顶点间路径:"; cin>>v1>>v2>>num; u=G.Locate_Vex(v1); v=G.Locate_Vex(v2); if(u == -1 || v == -1) { cout<<"顶点中有不符合要求的,操作失败"<<endl; } else { for(int i=0;i<G.GetVexNum();i++) visited[i]=false; cout<<"顶点 "<<v1<<" 到 "<<v2<<" 长度为 "<<num<<" 的简单路径如下:"<<endl; G.Print_X_Y_Path(u,v,num,-1); } cout<<"输入一个顶点名称,将输出所有经过它的回路:"; cin>>v1; u=G.Locate_Vex(v1); if(u == -1) { cout<<"顶点不存在,操作失败"<<endl; } else { for(v=0;v<G.GetVexNum();v++) visited[v]=false; cout<<"经过顶点 "<<v1<<" 的所有回路如下:"<<endl; G.Print_X_X_Path(u,u,-1); } return 0; }
测试结果:

输入顶点数和边数:5 6 输入顶点名称:v1 v2 v3 v4 v5 输入每条边对应的两个顶点:v1 v2 输入每条边对应的两个顶点:v1 v4 输入每条边对应的两个顶点:v2 v4 输入每条边对应的两个顶点:v2 v3 输入每条边对应的两个顶点:v3 v5 输入每条边对应的两个顶点:v4 v5 无向图构造完成 图的深度优先遍历为:v1 v4 v5 v3 v2 图的广度优先遍历为:v1 v4 v2 v5 v3 输入两个顶点名称和一个数字, 将输出长度为输入数字大小的两顶点间路径:v1 v3 3 顶点 v1 到 v3 长度为 3 的简单路径如下: v1-->v4-->v5-->v3 v1-->v4-->v2-->v3 输入一个顶点名称,将输出所有经过它的回路:v4 经过顶点 v4 的所有回路如下: v4-->v5-->v3-->v2-->v4 v4-->v5-->v3-->v2-->v1-->v4 v4-->v2-->v3-->v5-->v4 v4-->v2-->v1-->v4 v4-->v1-->v2-->v3-->v5-->v4 v4-->v1-->v2-->v4 Press any key to continue下面是生成的无向图示例:

为了更好得理解回溯的过程,可以画画像下面这样的示意图,比如我求 V1 到 V3的长度为3的路径的过程


图可能和你画的不一样,但是主要就是理清一下思路,不会在一重重的递归中乱掉

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值