图的实验报告.docx
《图的实验报告.docx》由会员分享,可在线阅读,更多相关《图的实验报告.docx(23页珍藏版)》请在冰豆网上搜索。
图的实验报告
《数据结构》
实验报告
题目:
图
一、实现图的邻接矩阵和邻接表存储
(一)需求分析
对于下图所示的有向图G,编写一个程序完成如下功能:
1.建立G的邻接矩阵并输出之
2.由G的邻接矩阵产生邻接表并输出之
3.再由2的邻接表产生对应的邻接矩阵并输出之
(二)系统设计
1、本程序中用到的所有抽象数据类型的定义;
typedefstruct
{intno;InfoTypeinfo;
}VertexType;
typedefstruct
//顶点类型
//图的定义
{intedges[MAXV][MAXV];
intvexnum,arcnum;
VertexTypevexs[MAXV];
}MGraph;
//图的邻接矩阵类型
typedefstructANode
//弧的结点结构类型
{intadjvex;
structANode*nextarc;
InfoTypeinfo;
}ArcNode;
typedefintVertex;
typedefstructVnode
//邻接表头结点的类型
{Vertexdata;
ArcNode*firstarc;
//指向第一条弧
}VNode;
typedefVNodeAdjList[MAXV];
//AdjList
是邻接表类型
typedefstruct
{
AdjListadjlist;
//邻接表
intn,e;
}ALGraph;
//图的邻接表类型
2、主程序的流程以及各程序模块之间的层次调用关系,函数的调用关系图:
Main()
DispMat(g);输出邻
MatToList(g,G);将邻接矩
DispAdj(G);输出
接矩阵g
阵g转换成邻接表G
邻接表G
3、列出各个功能模块的主要功能及输入输出参数
voidMatToList(MGraphg,ALGraph*&G)将邻接矩阵
voidDispMat(MGraphg)输出邻接矩阵g
voidDispAdj(ALGraph*G)输出邻接表G
intOutDegree(ALGraph*G,intv)求图中每个顶点的出度
g转换成邻接表
G
(三)调试分析
调试过程中还是出现了一些拼写错误,
经检查后都能及时修正。
有些是语法设计上的小
错误,比如一些参变量的初始值设置错误,
使得程序调试出错。
在小组讨论分析后纠正了这
些结果,并尽量改进了算法的性能,减小时间复杂度。
将邻接矩阵
g转换成邻接表
G,输出邻接矩阵
g,输出邻接表
G的算法时间复杂度都是
O(n^2)。
通过这次实验,对图的存储方法有了更深刻的印象。
(四)测试结果
测试结果:
(1)有向图G的邻接矩阵为
0104
0092
3580
0060
(2)图G的邻接矩阵转换成的邻接表为:
0:
13
1:
23
2:
012
3:
2
(五)用户手册
不需要输入参数
(六)附录
源程序
#include
#include
#defineMAXV100
#defineINF32767
//最大顶点个数
//INF表示∞
typedefintInfoType;
typedefstruct
{
intno;
//顶点编号
InfoTypeinfo;
}VertexType;
typedefstruct
//顶点其他信息
//顶点类型
//图的定义
{
intedges[MAXV][MAXV];
//邻接矩阵
intvexnum,arcnum;VertexTypevexs[MAXV];
//顶点数,弧数
//存放顶点信息
}MGraph;
//图的邻接矩阵类型
typedefstructANode
//弧的结点结构类型
{
intadjvex;
structANode*nextarc;
InfoTypeinfo;
//该弧的终点位置
//指向下一条弧的指针
//该弧的相关信息,这里用于存放权值
}ArcNode;
typedefintVertex;
typedefstructVnode
//邻接表头结点的类型
{
Vertexdata;
ArcNode*firstarc;
//顶点信息
//指向第一条弧
}VNode;
typedefVNodeAdjList[MAXV];
//AdjList
是邻接表类型
typedefstruct
{
AdjListadjlist;//邻接表
intn,e;//图中顶点数n和边数
}ALGraph;//图的邻接表类型
voidMatToList(MGraphg,ALGraph*&G)//将邻接矩阵
{
e
g转换成邻接表
G
inti,j,n=g.vexnum;
//n
为顶点数
ArcNode*p;
G=(ALGraph*)malloc(sizeof(ALGraph));
for(i=0;i//给邻接表中所有头结点的指针域置初值
G->adjlist[i].firstarc=NULL;
for(i=0;i//检查邻接矩阵中每个元素
for(j=n-1;j>=0;j--)
if(g.edges[i][j]!
=0)
//邻接矩阵的当前元素不为
0
{
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;
}
G->n=n;G->e=g.arcnum;
}
voidDispMat(MGraphg)
//输出邻接矩阵g
{
inti,j;
for(i=0;i{
for(j=0;jif(g.edges[i][j]==INF)
printf("%3s","∞");
else
printf("%3d",g.edges[i][j]);
printf("\n");
}
}
voidDispAdj(ALGraph*G)
//输出邻接表G
{
inti;
ArcNode*p;
for(i=0;in;i++)
{
p=G->adjlist[i].firstarc;
if(p!
=NULL)printf("%3d:
",i);
while(p!
=NULL)
{
printf("%3d",p->adjvex);
p=p->nextarc;
}
printf("\n");
}
}
intOutDegree(ALGraph*G,intv)//求图中每个顶点的出度
{
ArcNode*p;
intn=0;
p=G->adjlist[v].firstarc;
while(p!
=NULL)
{n++;
p=p->nextarc;
}
returnn;
}
voidmain()
{
inti,j;
MGraphg,g1;
ALGraph*G;
intA[MAXV][4]={
{0,1,0,4},
{0,0,9,2},
{3,5,8,0},
{0,0,6,0},};
g.vexnum=4;g.arcnum=8;
for(i=0;ifor(j=0;jg.edges[i][j]=A[i][j];
printf("\n");
printf("
(1)有向图G的邻接矩阵为:
\n");
DispMat(g);
G=(ALGraph*)malloc(sizeof(ALGraph));
printf("
(2)图G的邻接矩阵转换成邻接表为:
\n");
MatToList(g,G);
DispAdj(G);
}
运行后结果显示:
二、实现图的遍历算法
(一)需求分析
对于上图G,编写一个程序输出从顶点0开始的深度优先遍历序列(递归算法)和广度优先遍历序列(非递归算法)。
(二)系统设计
1.说明本程序中用到的所有抽象数据类型的定义;
typedefstruct{
charvexs[MaxVertexNum];//顶点表
intedges[MaxVertexNum][MaxVertexNum];//邻接矩阵,可看作边表
intn,e;//图中的顶点数n和边数e
}MGraph;//用邻接矩阵表示的图的类型
2.主程序的流程以及各程序模块之间的层次调用关系,画出函数的调用关系图。
Main()
CreatMGraph(G)
DFS(G);深度
BFS(G,0);以序号
为3的顶点开始广
建立邻接矩阵
优先遍历
度优先遍历
3.列出各个功能模块的主要功能及输入输出参数。
voidCreatMGraph(MGraph*G)
创建邻接矩阵
G
voidDFSM(MGraph*G,inti)以Vi为出发点对0-1邻接矩阵表示的图G进行DFS搜索
voidDFS(MGraph*G)深度优先遍历
voidBFS(MGraph*G,intk)以Vk为源点对用邻接矩阵表示的图G进行广度优先遍历
(三)调试分析
调试过程中还是出现了一些拼写错误,
经检查后都能及时修正。
有些是语法设计上的小
错误,比如一些参变量的初始值设置错误,
使得程序调试出错。
在小组讨论分析后纠正了这
些结果,并尽量改进了算法的性能,减小时间复杂度。
创建邻接矩阵算法的时间复杂度是O(2n+n^2),深度优先遍历和广度优先遍历的算法时
间复杂度都是O(n^2)。
通过这次实验,加深了对遍历图的递归和非递归的算法的印象。
(四)测试结果
输入节点数
8和边数
9,各节点标示
01234567,边是
01,02,13,14,25,26,37,47,56
,
运行后深度优先遍历是01374256,广度优先遍历是01234567。
(五)用户手册
根据提示输入节点和边数,然后再由提示输入各节点标示,接下来输入各边。
运行后便得
到深度优先遍历和广度优先遍历结果。
(六)附录
源程序:
#include"stdio.h"
#include"stdlib.h"
#defineMaxVertexNum100//定义最大顶点数
typedefstruct{
charvexs[MaxVertexNum];//顶点表
intedges[MaxVertexNum][MaxVertexNum];//邻接矩阵,可看作边表
intn,e;//图中的顶点数n和边数e
}MGraph;//用邻接矩阵表示的图的类型
voidCreatMGraph(MGraph*G)//建立邻接矩阵
{
inti,j,k;
chara;
printf("InputVertexNum(n)andEdgesNum(e):
");
scanf("%d,%d",&G->n,&G->e);//输入顶点数和边数scanf("%c",&a);
printf("InputVertexstring:
");
for(i=0;in;i++)
{
scanf("%c",&a);
G->vexs[i]=a;//读入顶点信息,建立顶点表
}
for(i=0;in;i++)
for(j=0;jn;j++)
G->edges[i][j]=0;//初始化邻接矩阵
printf("Inputedges,CreatAdjacencyMatrix\n");
for(k=0;ke;k++){//读入e条边,建立邻接矩阵
scanf("%d%d",&i,&j);//输入边(Vi,Vj)的顶点序号
G->edges[i][j]=1;
G->edges[j][i]=1;//若为无向图,矩阵为对称矩阵;若建立有向图,去掉该条语句
}
}
typedefenum{FALSE,TRUE}Boolean;
Booleanvisited[MaxVertexNum];
voidDFSM(MGraph*G,inti)
{//
以
Vi
为出发点对邻接矩阵表示的图
G进行
DFS
搜索,邻接矩阵是
0,1矩阵
intj;
printf("%c",G->vexs[i]);//访问顶点Vi
visited[i]=TRUE;//置已访问标志
for(j=0;jn;j++)//依次搜索Vi的邻接点
if(G->edges[i][j]==1&&!
visited[j])
DFSM(G,j);//(Vi,Vj)∈E,且
Vj
未访问过,故
Vj
为新出发点
}
voidDFS(MGraph*G)
{
inti;
for(i=0;in;i++)
visited[i]=FALSE;
//标志向量初始化
for(i=0;in;i++)
if(!
visited[i])
DFSM(G,i);
//Vi
未访问过
//以Vi为源点开始
DFS
搜索
}
voidBFS(MGraph*G,intk)
{//以Vk
为源点对用邻接矩阵表示的图
G进行广度优先搜索
inti,j,f=0,r=0;
intcq[MaxVertexNum];
for(i=0;in;i++)
visited[i]=FALSE;
for(i=0;in;i++)
cq[i]=-1;
printf("%c",G->vexs[k]);
visited[k]=TRUE;
cq[r]=k;//Vk
//定义队列
//标志向量初始化
//队列初始化
//访问源点Vk
已访问,将其入队。
注意,实际上是将其序号入队
while(cq[f]!
=-1){//队非空则执行
i=cq[f];f=f+1;//Vf出队
for(j=0;jn;j++)//依次Vi
if(G->edges[i][j]==1&&!
visited[j]){
printf("%c",G->vexs[j]);
visited[j]=TRUE;
r=r+1;cq[r]=j;//访问过
的邻接点Vj
//Vj未访问
//访问Vj
Vj入队
}
}
}
voidmain()
{
inti;
MGraph*G;
G=(MGraph*)malloc(sizeof(MGraph));//为图G申请内存空间
CreatMGraph(G);//建立邻接矩阵
printf("PrintGraphDFS:
");
DFS(G);//深度优先遍历
printf("\n");
printf("PrintGraphBFS:
");
BFS(G,0);//以序号为3的顶点开始广度优先遍历
printf("\n");
}
测试结果