第十二周项目4-利用遍历思想求解图问题(1-5)

来源:互联网 发布:139邮箱端口 编辑:程序博客网 时间:2024/05/17 23:23
  1. /*  
  2. Copyright (c)2016,烟台大学计算机与控制工程学院  
  3. All rights reserved.  
  4. 文件名称:第十二周项目4 - 利用遍历思想求解图问题(1-5).cpp  
  5. 作    者:朱建豪  
  6. 完成日期:2016年12月1日  
  7. 版 本 号:v1.0  
  8.   
  9. 问题描述: 假设图G采用邻接表存储,分别设计实现以下要求的算法,要求用区别于示例中的图进行多次测试,通过观察输出值,掌握相关问题的处理方法。   
  10.        (1)设计一个算法,判断顶点u到v是否有简单路径   
  11.        (2)设计一个算法输出图G中从顶点u到v的一条简单路径(设计测试图时,保证图G中从顶点u到v至少有一条简单路径)。   
  12.        (3)输出从顶点u到v的所有简单路径。   
  13.        (4)输出图G中从顶点u到v的长度为s的所有简单路径。   
  14.        (5)求图中通过某顶点k的所有简单回路(若存在)    
  15. 输入描述:若干测试数据。  
  16. 程序输出:相应的数据输出。   
  17. */    

(1)是否有简单路径:


源代码:

[cpp] view plain copy
  1. int visited[MAXV];     //定义存放节点的访问标志的全局数组    
  2. void ExistPath(ALGraph *G,int u,int v, bool &has)    
  3. {    
  4.     int w;    
  5.     ArcNode *p;    
  6.     visited[u]=1;    
  7.     if(u==v)    
  8.     {    
  9.         has=true;    
  10.         return;    
  11.     }    
  12.     p=G->adjlist[u].firstarc;    
  13.     while (p!=NULL)    
  14.     {    
  15.         w=p->adjvex;    
  16.         if (visited[w]==0)    
  17.             ExistPath(G,w,v,has);    
  18.         p=p->nextarc;    
  19.     }    
  20. }    
  21.     
  22. void HasPath(ALGraph *G,int u,int v)    
  23. {    
  24.     int i;    
  25.     bool flag = false;    
  26.     for (i=0; i<G->n; i++)    
  27.         visited[i]=0; //访问标志数组初始化    
  28.     ExistPath(G,u,v,flag);    
  29.     printf(" 从 %d 到 %d ", u, v);    
  30.     if(flag)    
  31.         printf("有简单路径\n");    
  32.     else    
  33.         printf("无简单路径\n");    
  34. }  

主函数:

[cpp] view plain copy
  1. int main()    
  2. {    
  3.     ALGraph *G;    
  4.     int A[5][5]=    
  5.     {    
  6.         {0,0,0,0,0},    
  7.         {0,0,1,0,0},    
  8.         {0,0,0,1,1},    
  9.         {0,0,0,0,0},    
  10.         {1,0,0,1,0},    
  11.     };  //请画出对应的有向图    
  12.     ArrayToList(A[0], 5, G);    
  13.     HasPath(G, 1, 0);    
  14.     HasPath(G, 4, 1);    
  15.     return 0;    
  16. }    


运行结果:

(2)输出简单路径:

源代码:

[cpp] view plain copy
  1. void FindAPath(ALGraph *G,int u,int v,int path[],int d)    
  2. {    
  3.     //d表示path中的路径长度,初始为-1    
  4.     int w,i;    
  5.     ArcNode *p;    
  6.     visited[u]=1;    
  7.     d++;    
  8.     path[d]=u;  //路径长度d增1,顶点u加入到路径中    
  9.     if (u==v)   //找到一条路径后输出并返回    
  10.     {    
  11.         printf("一条简单路径为:");    
  12.         for (i=0; i<=d; i++)    
  13.             printf("%d ",path[i]);    
  14.         printf("\n");    
  15.         return;         //找到一条路径后返回    
  16.     }    
  17.     p=G->adjlist[u].firstarc;  //p指向顶点u的第一个相邻点    
  18.     while (p!=NULL)    
  19.     {    
  20.         w=p->adjvex;    //相邻点的编号为w    
  21.         if (visited[w]==0)    
  22.             FindAPath(G,w,v,path,d);    
  23.         p=p->nextarc;   //p指向顶点u的下一个相邻点    
  24.     }    
  25. }    
  26.     
  27. void APath(ALGraph *G,int u,int v)    
  28. {    
  29.     int i;    
  30.     int path[MAXV];    
  31.     for (i=0; i<G->n; i++)    
  32.         visited[i]=0; //访问标志数组初始化    
  33.     FindAPath(G,u,v,path,-1);  //d初值为-1,调用时d++,即变成了0    
  34. }    

主函数:

[cpp] view plain copy
  1. int main()    
  2. {    
  3.     
  4.     ALGraph *G;    
  5.     int A[5][5]=    
  6.     {    
  7.         {0,0,0,0,0},    
  8.         {0,0,1,0,0},    
  9.         {0,0,0,1,1},    
  10.         {0,0,0,0,0},    
  11.         {1,0,0,1,0},    
  12.     };  //请画出对应的有向图    
  13.     ArrayToList(A[0], 5, G);    
  14.     APath(G, 1, 0);    
  15.     APath(G, 4, 1);    
  16.     return 0;    
  17. }    


运行结果:

(3)输出所有路径:


源代码:

[cpp] view plain copy
  1. void FindPaths(ALGraph *G,int u,int v,int path[],int d)    
  2. //d是到当前为止已走过的路径长度,调用时初值为-1    
  3. {    
  4.     int w,i;    
  5.     ArcNode *p;    
  6.     visited[u]=1;    
  7.     d++;            //路径长度增1    
  8.     path[d]=u;              //将当前顶点添加到路径中    
  9.     if (u==v && d>1)            //输出一条路径    
  10.     {    
  11.         printf("  ");    
  12.         for (i=0; i<=d; i++)    
  13.             printf("%d ",path[i]);    
  14.         printf("\n");    
  15.     }    
  16.     p=G->adjlist[u].firstarc; //p指向u的第一条边    
  17.     while(p!=NULL)    
  18.     {    
  19.         w=p->adjvex;     //w为u的邻接顶点    
  20.         if (visited[w]==0)      //若顶点未标记访问,则递归访问之    
  21.             FindPaths(G,w,v,path,d);    
  22.         p=p->nextarc; //找u的下一个邻接顶点    
  23.     }    
  24.     visited[u]=0;   //恢复环境    
  25. }    
  26.     
  27.     
  28. void DispPaths(ALGraph *G,int u,int v)    
  29. {    
  30.     int i;    
  31.     int path[MAXV];    
  32.     for (i=0; i<G->n; i++)    
  33.         visited[i]=0; //访问标志数组初始化    
  34.     printf("从%d到%d的所有路径:\n",u,v);    
  35.     FindPaths(G,u,v,path,-1);    
  36.     printf("\n");    
  37. }    

主函数:

[cpp] view plain copy
  1. int main()    
  2. {    
  3.     ALGraph *G;    
  4.     int A[5][5]=    
  5.     {    
  6.         {0,1,0,1,0},    
  7.         {1,0,1,0,0},    
  8.         {0,1,0,1,1},    
  9.         {1,0,1,0,1},    
  10.         {0,0,1,1,0}    
  11.     };  //请画出对应的有向图    
  12.     ArrayToList(A[0], 5, G);    
  13.     DispPaths(G, 1, 4);    
  14.     return 0;    
  15. }    

运行结果:

(4)输出一些简单回路:


源代码:

[cpp] view plain copy
  1. void SomePaths(ALGraph *G,int u,int v,int s, int path[],int d)  
  2. //d是到当前为止已走过的路径长度,调用时初值为-1  
  3. {  
  4.     int w,i;  
  5.     ArcNode *p;  
  6.     visited[u]=1;  
  7.     d++;            //路径长度增1  
  8.     path[d]=u;              //将当前顶点添加到路径中  
  9.     if (u==v && d==s)           //输出一条路径  
  10.     {  
  11.         printf("  ");  
  12.         for (i=0; i<=d; i++)  
  13.             printf("%d ",path[i]);  
  14.         printf("\n");  
  15.     }  
  16.     p=G->adjlist[u].firstarc; //p指向u的第一条边  
  17.     while(p!=NULL)  
  18.     {  
  19.         w=p->adjvex;     //w为u的邻接顶点  
  20.         if (visited[w]==0)      //若顶点未标记访问,则递归访问之  
  21.             SomePaths(G,w,v,s,path,d);  
  22.         p=p->nextarc; //找u的下一个邻接顶点  
  23.     }  
  24.     visited[u]=0;   //恢复环境  
  25. }  
  26.   
  27. void DispSomePaths(ALGraph *G,int u,int v, int s)  
  28. {  
  29.     int i;  
  30.     int path[MAXV];  
  31.     for (i=0; i<G->n; i++)  
  32.         visited[i]=0; //访问标志数组初始化  
  33.     printf("从%d到%d长为%d的路径:\n",u,v,s);  
  34.     SomePaths(G,u,v,s,path,-1);  
  35.     printf("\n");  
  36. }  

主函数:

[cpp] view plain copy
  1. int main()    
  2. {    
  3.     ALGraph *G;    
  4.     int A[5][5]=    
  5.     {    
  6.         {0,1,0,1,0},    
  7.         {1,0,1,0,0},    
  8.         {0,1,0,1,1},    
  9.         {1,0,1,0,1},    
  10.         {0,0,1,1,0}    
  11.     };  //请画出对应的有向图    
  12.     ArrayToList(A[0], 5, G);    
  13.     DispSomePaths(G, 1, 4, 3);    
  14.     return 0;    
  15. }    

运行结果:



(5)输出通过一个节点的所有简单回路:


源代码:

[cpp] view plain copy
  1. void DFSPath(ALGraph *G,int u,int v,int path[],int d)  
  2. //d是到当前为止已走过的路径长度,调用时初值为-1  
  3. {  
  4.     int w,i;  
  5.     ArcNode *p;  
  6.     visited[u]=1;  
  7.     d++;  
  8.     path[d]=u;  
  9.     p=G->adjlist[u].firstarc;   //p指向顶点u的第一条边  
  10.     while (p!=NULL)  
  11.     {  
  12.         w=p->adjvex;            //w为顶点u的相邻点  
  13.         if (w==v && d>0)        //找到一个回路,输出之  
  14.         {  
  15.             printf("  ");  
  16.             for (i=0; i<=d; i++)  
  17.                 printf("%d ",path[i]);  
  18.             printf("%d \n",v);  
  19.         }  
  20.         if (visited[w]==0)          //w未访问,则递归访问之  
  21.             DFSPath(G,w,v,path,d);  
  22.         p=p->nextarc;       //找u的下一个邻接顶点  
  23.     }  
  24.     visited[u]=0;           //恢复环境:使该顶点可重新使用  
  25. }  
  26.   
  27. void FindCyclePath(ALGraph *G,int k)  
  28. //输出经过顶点k的所有回路  
  29. {  
  30.     int path[MAXV],i;  
  31.     for (i=0; i<G->n; i++)  
  32.         visited[i]=0; //访问标志数组初始化  
  33.     printf("经过顶点%d的所有回路\n",k);  
  34.     DFSPath(G,k,k,path,-1);  
  35.     printf("\n");  
  36. }  

主函数:

[cpp] view plain copy
  1. int main()  
  2. {  
  3.     ALGraph *G;  
  4.     int A[5][5]=  
  5.     {  
  6.         {0,1,1,0,0},  
  7.         {0,0,1,0,0},  
  8.         {0,0,0,1,1},  
  9.         {0,0,0,0,1},  
  10.         {1,0,0,0,0}  
  11.     };  //请画出对应的有向图  
  12.     ArrayToList(A[0], 5, G);  
  13.     FindCyclePath(G, 0);  
  14.     return 0;  
  15. }  

运行结果:

知识点总结:

图的遍历。

0 0