图遍历的演示
[问题描述]
很多涉及图上操作的算法都是以图的遍历操作为基础的。试写一个程序,演示无向图的遍历操作。
以邻接表为存储结构,实现连通无向图的深度优先和广度优先遍历。以用户指定的结点为起点,分别输出每种遍历下的结点访问序列和相应生成树的边集。
借助于栈类型(自己定义和实现)将深度优先遍历用非递归算法实现。(非递归算法的实现为选做内容,如能实现,适当加分)
[测试数据]
在《数据结构》教材中任意找两个无向图作为测试数据。
[实现提示]
设图的结点不超过30个,每个结点用一个编号表示(如果一个图有n个结点,则它们的编号分别为1,2,…,n)。通过输入图的全部边输入一个图,每个边为一个数对,可以对边的输入顺序作出某种限制。注意,生成树的边是有向边,端点顺序不能颠倒。
下面是代码:
广搜的:
#include<cstdio> #include<cstring> const int NN=100;//点的数量 const int MM=1000;//边的数量 /* 邻接表 */ struct G { int v,next; }E[MM]; int p[NN],T; /* 搜索标记数组 */ int dd[NN]; /* 用数组实现队列 */ int qw[NN]; /* 记录边集 */ int to[MM][2]; int tol; //边的个数 void add(int u,int v) { E[T].v=v; E[T].next=p[u]; p[u]=T++; } void find_path(int st,int n) { int i,u,v,head,tail; for(i=1;i<=n;i++) dd[i]=-1; dd[st]=0; qw[head=tail=0]=st; printf("遍历顺序为:\n%d",st); while(head<=tail) { u=qw[head++]; for(i=p[u];i+1;i=E[i].next) { v=E[i].v; if(dd[v]==-1) { printf(" %d",v); to[tol][0]=u; to[tol++][1]=v; dd[v]=dd[u]+1; qw[++tail]=v; } } } puts(""); } int main() { int u,v,n,m; printf("输入点和边的数量\n"); scanf("%d%d",&n,&m); /* 初始化 */ memset(p,-1,sizeof(p)); T=0; tol=0; printf("输入边的信息\n"); for(int i=0;i<m;i++) { scanf("%d%d",&u,&v); add(u,v); add(v,u); } int x=1;//x可以是任意一个点 find_path(x,n); printf("边集\n"); for(int i=0;i<tol;i++) { printf("%d %d\n",to[i][0],to[i][1]); } return 0; }
深搜的:
#include<cstdio> #include<cstring> const int NN=100;//点的数量 const int MM=1000;//边的数量 /* 邻接表 */ struct G { int v,next; }E[MM]; int p[NN],T; /* 搜索标记数组 */ bool vis[NN]; /* 记录边集 */ int to[MM][2]; int tol; //边的个数 void add(int u,int v) { E[T].v=v; E[T].next=p[u]; p[u]=T++; } void dfs(int x) { for(int i=p[x];i+1;i=E[i].next) { int v=E[i].v; if(!vis[v]) { printf(" %d",v); to[tol][0]=x; to[tol++][1]=v; vis[v]=true; dfs(v); } } } int main() { int u,v,n,m; printf("输入点和边的数量\n"); scanf("%d%d",&n,&m); /* 初始化 */ memset(vis,false,sizeof(vis)); memset(p,-1,sizeof(p)); T=0; printf("输入边的信息\n"); for(int i=0;i<m;i++) { scanf("%d%d",&u,&v); add(u,v); add(v,u); } int x=1;//x可以是任意一个点 vis[x]=true; printf("遍历顺序为:\n%d",x); dfs(x); puts(""); printf("边集\n"); for(int i=0;i<tol;i++) { printf("%d %d\n",to[i][0],to[i][1]); } return 0; }
注意:MM存的是双向边,所以MM的上限值应该是输入的边(m)的两倍。边集,输出顺序,是有序的,我是默认图是连通的。