提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
属于是学到了图论的遍历,深度的优先遍历运用的比较多。深度优先遍历其实就是一个递归的过程,也就是树的前序遍历。而图的广度优先遍历类似于树的层序遍历。
在完成
相应的图的编程作业,二叉树的作业中,也都运用了多次C语言中的scanf,也让我学到了新的知识点。每次运用完一次scanf,其实回车都被保存了,会在下一次scanf的使用被赋予,就直接导致程序的结束。所以中间应该加入getchar()。
scanf("%d %d",&m,&n);
getchar();
scanf("%c%c", &c1, &c2);
在图的作业中,寻找两个顶点间是否存在路径和一个图中有几个连通分量,都运用到了深度优先遍历。所以准备记录一下,使用的一些代码。
图的两个顶尖是否存在路径:
#include <stdio.h> #define MAX 100 typedef struct Tree { char vexs[MAX]; \\顶点表 int arc[MAX][MAX]; \\邻接矩阵 int numt,nume; \\顶点数和边数 } TNree; void TU(TNree * t,char a[MAX],int &y) \\创建图的邻接矩阵(无向图) { int m,n,i=0,j=0,p,q; while(a[i]!='!') { t->vexs[i] = a[i]; i++; } y = i; \\就是图的顶点数 for(p=0;p<i;p++) //初始化 { for(q=0;q<i;q++) { t->arc[p][q] = 0; } } for(j=0;j<MAX;j++) { scanf("%d %d",&m,&n); if(m==-1&&n==-1) { break; } t->arc[m][n] = 1; \\无向图的邻接矩阵是对称的 } } void HANTAO(TNree *t,int m) \\输出整个邻接矩阵 { int i,j; for(i = 0;i<m;i++) { for(j=0;j<m;j++) { printf("%d ",t->arc[i][j]); } printf("\n"); } } void wuyu(TNree *t,int &i,int &j,int h) \\寻找两个顶点的下标 { int m,n; char c1, c2; getchar(); scanf("%c%c", &c1, &c2); for(m=0;m<h;m++) { if(t->vexs[m]==c1) { i = m; } } for(n=0;n<h;n++) { if(t->vexs[n]==c2) { j = n; } } } void DFS(TNree *t, int i, int j, int visited[], int *result,int m) \\深度的优先遍历 { int k; if (i == j) { *result = 1; \\两个顶点间存在路径。 } visited[i] = 1; for (k = 0;k<m; k++) { if (t->arc[i][k] != 0 && !visited[k]) //如果两个顶点间存在路径,并且未被调用过 { DFS(t, k, j, visited,result,m); } } } int main() { int i,j; TNree t; char a[MAX]; int result = 0; int visited[MAX] = {0}; //数组的初始化,全为0 char g; int n,m; for(n=0;n<MAX;n++) { scanf("%c",&a[n]); if(a[n]=='!') { break; } } TU(&t,a,m); wuyu(&t,i,j,m); HANTAO(&t,m); printf("\n"); DFS(&t,i,j,visited,&result,m); if (result) { printf("T\n"); // 存在路径 } else { printf("F\n"); // 不存在路径 } return 0; }
图存在几个连通分量:
#include <stdio.h> #define MAX 100 typedef struct Tree { char vexs[MAX]; int arc[MAX][MAX]; int numt,nume; } TNree; void TU(TNree * t,char a[MAX],int &y) { int m,n,i=0,j=0,p,q; while(a[i]!='!') { t->vexs[i] = a[i]; i++; } y = i; for(p=0;p<i;p++) { for(q=0;q<i;q++) { t->arc[p][q] = 0; } } for(j=0;j<MAX;j++) { scanf("%d %d",&m,&n); if(m==-1&&n==-1) { break; } t->arc[m][n] = 1; t->arc[n][m] = 1; } } void DFS(TNree *t, int i,int m,int visited[]) { int k; visited[i] = 1; for (k = 0;k<m; k++) { if (t->arc[i][k] != 0 && !visited[k]) { DFS(t, k,m,visited); } } } int main() { TNree t; int visited[MAX]={0}; char a[MAX]; int n,m,count=0; for(n=0;n<MAX;n++) { scanf("%c",&a[n]); if(a[n]=='!') { break; } } TU(&t,a,m); for(n=0;n<m;n++) { if(!visited[n]) { DFS(&t,n,m,visited); count++; } } printf("%d",count); return 0; }
思路其实也就是开始从0深度遍历,在DFS里就会走完一个联通图,将其visited都变为1,这样就得到一个连通分量了。之后如果还有visited不为1,那就又得到一个新的连通分量。
总结
其实学完图的深度和广度优先遍历,在写作业时,完全没想到可以用在查图两个顶点是否存在路径和有几个连通分量,还是在网上参考了别人,才意识到深度优先遍历,作用这么大。只能说还是得多写写,多练练,多想想。