实验14 TYJ图的遍历(深度和广度优先)
第1关:图的深度优先和广度优先遍历
任务描述
本关任务:编写一个程序完成图的邻接矩阵到邻接表的转换,对邻接表存储的图进行递归和非递归深度优先以及广度优先遍历。
相关知识
为了完成本关任务,你需要掌握:1.广度优先算法,2.深度优先递归算法和非递归算法 3.顺序栈的操作,4.顺序队列的操作。
测试说明
平台会对你编写的代码进行测试:
测试输入:测试数据已在代码中提供;
预期输出:
图G的邻接矩阵:
0 5 0 7 0 0
0 0 4 0 0 0`
8 0 0 0 0 9
0 0 5 0 0 6
0 0 0 5 0 0
3 0 0 0 1 0
图G的邻接表:
0: 1 3
1: 2
2: 0 5
3: 2 5
4: 3
5: 0 4
从顶点0开始的DFS(递归算法):
0 1 2 5 4 3
从顶点0开始的DFS(非递归算法):
0 1 2 5 4 3
从顶点0开始的BFS(递归算法):
0 1 3 2 5 4
```
开始你的任务吧,祝你成功!
#include <stdio.h>
#include <malloc.h>
#define MAXV 100 /*最大顶点个数*/
#define INF 32767
typedef int InfoType;
/*以下定义邻接矩阵类型*/
typedef struct
{ int no; /*顶点编号*/
InfoType info; /*顶点其他信息*/
} VertexType; /*顶点类型*/
typedef struct /*图的定义*/
{ int edges[MAXV][MAXV]; /*邻接矩阵*/
int vexnum,arcnum; /*顶点数,弧数*/
VertexType vexs[MAXV]; /*存放顶点信息*/
} MGraph; /*图的邻接矩阵类型*/
/*以下定义邻接表类型*/
typedef struct ANode /*弧的结点结构类型*/
{ int adjvex; /*该弧的终点位置*/
struct ANode *nextarc; /*指向下一条弧的指针*/
InfoType info; /*该弧的相关信息,这里用于存放权值*/
} ArcNode;
typedef int Vertex;
typedef struct Vnode /*邻接表头结点的类型*/
{ Vertex data; /*顶点信息*/
ArcNode *firstarc; /*指向第一条弧*/
} VNode;
typedef VNode AdjList[MAXV]; /*AdjList是邻接表类型 */
typedef struct
{ AdjList adjlist; /*邻接表VNode adjlist[MAXV]*/
int n,e; /*图中顶点数n和边数e*/
} ALGraph; /*图的邻接表类型*/
int visited[MAXV]; /*全局数组*/
void MatToList(MGraph g,ALGraph* G); /*邻接矩阵转换为邻接表*/
void DispMat(MGraph g); /*输出邻接矩阵*/
void DispAdj(ALGraph *G); /*输出邻接表*/
void DFS(ALGraph *G,int v); /*深度优先遍历邻接表*/
void DFS1(ALGraph *G,int v); /*非递归深度优先遍历邻接表*/
void BFS(ALGraph *G,int v); /*广度优先遍历邻接表*/
int main()
{
int i,j;
MGraph g;
ALGraph *G;
int A[MAXV][6]={
{0,5,0,7,0,0},
{0,0,4,0,0,0},
{8,0,0,0,0,9},
{0,0,5,0,0,6},
{0,0,0,5,0,0},
{3,0,0,0,1,0}};
g.vexnum=6;g.arcnum=10;
for (i=0;i<g.vexnum;i++) /*建立图的邻接矩阵*/
for (j=0;j<g.vexnum;j++)
g.edges[i][j]=A[i][j];
printf("图G的邻接矩阵:\n");
DispMat(g);
G=(ALGraph *)malloc(sizeof(ALGraph));
MatToList(g,G); /*图G的邻接矩阵转换成邻接表*/
printf("图G的邻接表:\n");
DispAdj(G);
printf("从顶点0开始的DFS(递归算法):\n");
DFS(G,0);
printf("\n");
printf("从顶点0开始的DFS(非递归算法):\n");
DFS1(G,0);
printf("从顶点0开始的BFS(递归算法):\n");
BFS(G,0);printf("\n");
}
void MatToList(MGraph g,ALGraph* G)
/*将邻接矩阵g转换成邻接表G*/
{
int i,j,n=g.vexnum; /*n为顶点数*/
ArcNode *p;
for (i=0;i<n;i++) /*给邻接表中所有头结点的指针域置初值*/
G->adjlist[i].firstarc=NULL;
for (i=0;i<n;i++) /*检查邻接矩阵中每个元素*/
for (j=n-1;j>=0;j--)
if (g.edges[i][j]!=0) /*邻接矩阵的当前元素不为0*/
{
/*************Begin1********************/
p=(ArcNode *)malloc(sizeof(ArcNode)); //创建一个节点*p
p->adjvex=j;
p->info=g.edges[i][j];
p->nextarc=G->adjlist[i].firstarc; //采用头插法插入*p
G->adjlist[i].firstarc=p;
/*************End1********************/
}
G->n=n;G->e=g.arcnum;
}
void DispMat(MGraph g)
/*输出邻接矩阵g*/
{
int i,j;
for (i=0;i<g.vexnum;i++)
{
for (j=0;j<g.vexnum;j++)
if (g.edges[i][j]==INF)
printf("%3s","∞");
else
printf("%3d",g.edges[i][j]);
printf("\n");
}
}
void DispAdj(ALGraph *G)
/*输出邻接表G*/
{
int i;
ArcNode *p;
for (i=0;i<G->n;i++)
{
p=G->adjlist[i].firstarc;
if (p!=NULL) printf("%3d: ",i);
while (p!=NULL)
{
printf("%3d",p->adjvex);
p=p->nextarc;
}
printf("\n");
}
}
void DFS(ALGraph *G,int v)
{
ArcNode *p;
visited[v]=1; /*置已访问标记*/
printf("%3d",v); /*输出被访问顶点的编号*/
p=G->adjlist[v].firstarc; /*p指向顶点v的第一条弧的弧头结点*/
while (p!=NULL)
{
/*************Begin2********************/
if(visited[p->adjvex]==0)
DFS(G,p->adjvex);
/*************End2********************/
p=p->nextarc;
}
}
void DFS1(ALGraph *G,int v)
{
int i,visited[MAXV];
int St[MAXV],top=-1;//定义顺序栈并初始化栈顶指针
ArcNode *p;
for (i=0;i<G->n;i++)
visited[i]=0; /*结点访问标志均置成0*/
printf("%3d",v); /*访问顶点v*/
top++; /*v入栈*/
St[top]=v;
visited[v]=1;
while (top>=-1) /*栈不空时循环*/
{
/*************Begin3********************/
v=St[top];top--;
p=G->adjlist[v].firstarc;
/*************End3********************/
while (p!=NULL && visited[p->adjvex]==1)
p=p->nextarc;
if (p==NULL) /*若没有退到前一个*/
top--;
else /*若有,选择一个*/
{
/*************Begin4********************/
v=p->adjvex;
printf("%3d",v);
visited[v]=1;
top++;
St[top]=v;
/*************End4********************/
}
}
printf("\n");
}
void BFS(ALGraph *G,int v)
{
ArcNode *p;
int queue[MAXV],front=0,rear=0; /*定义循环队列并初始化*/
int visited[MAXV]; /*定义存放结点的访问标志的数组*/
int w,i;
for (i=0;i<G->n;i++) visited[i]=0; /*访问标志数组初始化*/
printf("%3d",v); /*输出被访问顶点的编号*/
visited[v]=1; /*置已访问标记*/
rear=(rear+1)%MAXV;
queue[rear]=v; /*v进队*/
while (front!=rear) /*若队列不空时循环*/
{
/*************Begin5********************/
front=(front+1)%MAXV;
w=queue[front]; //出队并赋给w
p=G->adjlist[w].firstarc;
/*************End5********************/
while (p!=NULL)
{
/*************Begin6********************/
if (visited[p->adjvex]==0)
{
printf("%3d",p->adjvex); //访问之
visited[p->adjvex]=1;
rear=(rear+1)%MAXV; //该顶点进队
queue[rear]=p->adjvex;
/*************End6********************/
}
p=p->nextarc; /*找下一个邻接顶点*/
}
}
printf("\n");
}
点个赞呗!谢谢您!