(图的遍历)以邻接矩阵和邻接表的方式存储连通图。然后分别用深度优先或广度优先算法遍历邻接矩方式存储的图和邻接表方式存储的图。
实验目的
1.掌握图的基本存储方法;
2.掌握有关图的操作算法并用高级语言编程实现。
实验数据(图)
运行结果
代码实现
#include<stdio.h>
#include<malloc.h>
typedef int InfoType;
#define MAXV 100 //最大顶点个数
#define INF 32767 //INF表示无穷大
//以下定义邻接矩阵类型
typedef struct
{
int no;//顶点编号
InfoType info;//顶点其他信息
}VertexType;//顶点类型
typedef struct
{//图的定义
int edges[MAXV][MAXV]; //邻接矩阵
int n;//顶点数
int e;//边数
VertexType vex[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;//邻接3表
int n;//顶点数
int e;//边数
}ALGraph;//图的邻接表类型
//不带权图的算法
void MatToList(MGraph g,ALGraph *&G)
{//将邻接矩阵g转换成邻接表G
int i,j;
ArcNode *p;
G=(ALGraph *)malloc(sizeof(ALGraph));
for(i=0;i<g.n;i++)//给邻接表中所有头节点的指针域置初值
G->adjlist[i].firstarc=NULL;
for(i=0;i<g.n;i++)
for(j=g.n-1;j>=0;j--)
if(g.edges[i][j]!=0)
{
p=(ArcNode *)malloc(sizeof(ArcNode));
p->adjvex=j;
p->nextarc=G->adjlist[i].firstarc;
G->adjlist[i].firstarc=p;
}
G->n=g.n;G->e=g.e;
}
void DisMat(MGraph g)//输出邻接矩阵
{
int i,j;
for(i=0;i<g.n;i++)
{
for(j=0;j<g.n;j++)//输出各个邻接点的值
printf("%3d",g.edges[i][j]);
printf("\n");
}
}
void DispAdj(ALGraph *G)//输出邻接表
{
int i;
ArcNode *p;
for(i=0;i<G->n;i++)
{
p=G->adjlist[i].firstarc;
printf("%3d(V%d):",i,i+1);//输出第一个顶点的邻接表内容
while(p!=NULL)//循环输出目标顶点的邻接表内容
{
printf("%3d",p->adjvex);//输出目标顶点邻接的终端顶点
p=p->nextarc;//p转下一个边
}
printf("\n");
}
}
int visited[MAXV];//遍历局部变量
void DFS(ALGraph *G,int v)//输出图G中从顶点v出发的深度优先生成树
{
ArcNode *p;
visited[v]=1;//置已访问标记
p=G->adjlist[v].firstarc;//p指向顶点v的第一条边
while(p!=NULL)
{
if(visited[p->adjvex]==0)//若p->adjvex顶点未访问,则递归访问它
{
printf("<%d,%d>",v,p->adjvex);//输出生成树的一条边
DFS(G,p->adjvex);//将一个顶点的边全部输出
}
p=p->nextarc;//p指向顶点v的下一条边
}
}
void BFS(ALGraph *G,int v)//输出图G中从顶点v出发的广度优先生成树
{
ArcNode *p;
int queue[MAXV],front=0,rear=0;//定义循环队列并初始化
int w,i;
for(i=0;i<G->n;i++)
visited[i]=0;//访问标志数组初始化
visited[v]=1;//将开始访问的v顶点置已访问标记
queue[rear]=v;//v进队
rear=(rear+1)%MAXV;//队尾指针加1
while(front!=rear)//队列不空时循环
{
w=queue[front];//出队并赋给w
front=(front+1)%MAXV;//队头指针加1
p=G->adjlist[w].firstarc;//找与顶点w邻接的第一个顶点
while(p!=NULL)//同一层广度遍历
{
if(visited[p->adjvex]==0)//若当前邻接顶点未被访问
{
printf("<%d,%d>",w,p->adjvex);//输出生成树的一条边
visited[p->adjvex]=1;//置该顶点已被访问的标志
queue[rear]=p->adjvex;
rear=(rear+1)%MAXV;//该顶点进队
}
p=p->nextarc;
}
}
printf("\n");
}
void main()
{
int i,j;
MGraph g,g1;
ALGraph *G;
int A[MAXV][9]={{0,1,0,0,0,1,0,0,0},{1,0,1,0,0,0,1,0,0},{0,1,0,1,0,0,0,1,0},{0,0,1,0,1,0,0,1,0},
{0,0,0,1,0,1,0,0,0},{1,0,0,0,1,0,0,0,0},{0,1,0,0,0,0,0,1,1},{0,0,1,1,0,0,1,0,1},{0,0,0,0,0,0,1,1,0}};
g.n=9;g.e=12;
for(i=0;i<g.n;i++)
for(j=0;j<g.n;j++)
g.edges[i][j]=A[i][j];
printf("无向图G的邻接矩阵:\n");
DisMat(g);
G=(ALGraph *)malloc(sizeof(ALGraph));
printf("图G的邻接矩阵转换成邻接表:\n");
MatToList(g,G);
DispAdj(G);
printf("深度优先生成树;");
DFS(G,3);printf("\n");
for(i=0;i<g.n;i++)
visited[i]=0;
printf("广度优先生成树:");
BFS(G,3);printf("\n");
}