图的遍历.docx

上传人:b****0 文档编号:12612487 上传时间:2023-04-20 格式:DOCX 页数:22 大小:185.26KB
下载 相关 举报
图的遍历.docx_第1页
第1页 / 共22页
图的遍历.docx_第2页
第2页 / 共22页
图的遍历.docx_第3页
第3页 / 共22页
图的遍历.docx_第4页
第4页 / 共22页
图的遍历.docx_第5页
第5页 / 共22页
点击查看更多>>
下载资源
资源描述

图的遍历.docx

《图的遍历.docx》由会员分享,可在线阅读,更多相关《图的遍历.docx(22页珍藏版)》请在冰豆网上搜索。

图的遍历.docx

图的遍历

 

数据结构课程设计报告

图遍历的演示

 

姓名:

贾西洋

学号:

201101050909

院系:

信息学院

班级:

信管11-1

 

二〇一三年六月

图遍历的演示

题目:

很多涉及图上操作的算法都是以图的遍历操作为基础的。

试写一个程序,演示在连通的无向图上访问全部结点的操作。

一、需求分析

1、以邻接多重表为存储结构;

2、实现连通和非连通的无向图的深度优先和广度优先遍历;

3、要求利用栈实现无向图的深度优先遍历;

4、以用户指定的结点为起点,分别输出每种遍历下的结点访问序列和生成树的边集;

二、概要设计

1、设定图的抽象数据类型:

ADTGraph{

数据对象V:

V是具有相同特性的数据元素的集合,称为点集.

数据关系R:

R={VR}

VR={(v,w)|v,w属于V,(v,w)表示v和w之间存在的路径}

基本操作P:

CreatGraph(&G,V,VR)

初始条件:

V是图的顶点集,VR是图中弧的集合.

操作结果:

按V和VR是定义构造图G.

DestroyGraph(&G)

初始条件:

图G存在

操作结果:

销毁图G

LocateVex(G,u)

初始条件:

图G存在,u和G中顶点有相同的特征

操作结果:

若图G中存在顶点u,则返回该顶点在图中的位置;否则返回其他信息

GetVex(G,v)

初始条件:

图G存在,v是G中顶点

操作结果:

返回v的值

FirstAjvex(G,v)

初始条件:

图G存在,v是G中顶点

操作结果:

返回v的第一个邻接顶点,若顶在图中没有邻接顶点,则返回为空

NextAjvex(G,v,w)

初始条件:

图G存在,v是G中顶点,w是v的邻接顶点

操作结果:

返回v的下一个邻接顶点,若w是v的最后一个邻接顶点,则返回空

DeleteVexx(&G,v)

初始条件:

图G存在,v是G中顶点

操作结果:

删除顶点v已经其相关的弧

DFSTraverse(G,visit())

初始条件:

图G存在,visit的顶点的应用函数

操作结果:

对图进行深度优先遍历,在遍历过程中对每个结点调用visit函数一次,一旦visit失败,则操作失败

BFSTraverse(G,visit())

初始条件:

图G存在,visit的顶点的应用函数

操作结果:

对图进行广度优先遍历,在遍历过程中对每个结点调用visit函数一次,一旦visit失败,则操作失败

}ADTGraph

2、设定队列的抽象数据类型:

ADTQueue{

数据对象:

D={ai|ai属于Elemset,i=1,2….,n,n>=0}

数据关系:

R1={|ai-1,ai属于D,i=1,2,…,n}

约定ai为端为队列头,an为队列尾

基本操作:

InitQueue(&Q)

操作结果:

构造一个空队列Q

DestryoQueue(&Q)

初始条件:

队列Q已存在。

操作结果:

队列Q被销毁,不再存在。

EnQueue(&Q,e)

初始条件:

队列Q已经存在

操作结果:

插入元素e为Q的新的队尾元素

DeQueue(&Q,&E)

初始条件:

Q为非空队列

操作结果:

删除Q的队尾元素,并用e返回其值

QueueEmpty(Q)

初始条件:

队列已经存在

操作结果:

若队列为空,则返回TRUE,否则返回FLASE

}ADTQueue

3、本程序包含四个模块:

1)主程序模块

voidmain()

{

手动构造一个图;

进行深度优先遍历图;

进行广度优先遍历图;

};

2)手动构造一个图-自己输入图的顶点和边生成一个图;

3)进行深度优先遍历图-打出遍历的结点序列和边集;

4)进行广度优先遍历图-打出遍历的结点序列和边集;

三、详细设计

1、顶点,边和图类型

#defineMAX_INFO10/*相关信息字符串的最大长度+1*/

#defineMAX_VERTEX_NUM20/*图中顶点数的最大值*/

intvisited[MAX_VERTEX_NUM];/*全局变量,访问标志数组*/

typedefcharInfoType;/*相关信息类型*/

typedefcharVertexType;/*字符类型*/

typedefenum{unvisited,visited}VisitIf;

typedefstructEBox/*边结点类型*/

{

intmark;/*访问标记*/

intivex,jvex;/*该边依附的两个顶点位置*/

structEBox*ilink,*jlink;/*分别指向依附这两个顶点的下一条边*/

}EBox;

typedefstructVexBox/*顶点结点类型*/

{

chardata[MAX_LEN];

EBox*fistedge;/*指向第一条依附该顶点的边*/

}VexBox;

typedefstruct

{

VexBoxlist[MAX_VERTEX_NUM];

intvexnum,edgenum;/*无向图当前顶点数和边数*/

}AMLGraph;

图的基本操作如下:

intLocateVex(AMLGraphG,VertexTypeu);

//查G和u有相同特征的顶点,若存在则返回该顶点在无向图中位置;否则返回-1。

VertexType&GetVex(AMLGraphG,intv);

//以v返回邻接多重表中序号为i的顶点。

intFirstAdjVex(AMLGraphG,VertexTypev);

//返回v的第一个邻接顶点的序号。

若顶点在G中没有邻接顶点,则返回-1。

intNextAdjVex(AMLGraphG,VertexTypev,VertexTypew);

//返回v的(相对于w的)下一个邻接顶点的序号若w是v的最后一个邻接点,则返回-1。

voidCreateGraph(AMLGraph&G);

//采用邻接多重表存储结构,构造无向图G。

StatusDeleteArc(AMLGraph&G,VertexTypev,VertexTypew);

//在G中删除边

StatusDeleteVex(AMLGraph&G,VertexTypev);

//在G中删除顶点v及其相关的边。

voidDestroyGraph(AMLGraph&G);

//销毁一个图

voidDisplay(AMLGraphG);

//输出无向图的邻接多重表G。

voidDFSTraverse(AMLGraphG,VertexTypestart,int(*visit)(VertexType));

//从start顶点起,(利用栈非递归)深度优先遍历图G。

voidBFSTraverse(AMLGraphG,VertexTypestart,int(*Visit)(VertexType));

//从start顶点起,广度优先遍历图G。

voidMarkUnvizited(AMLGraphG);//置边的访问标记为未被访问。

其中部分操作的算法如下:

voidCreateGraph(AMLGraph*p)/*创建无向图*/

{

inti,j,k;

EBox*q;

printf("\n\t\t\t请输入图的结点个数和边的个数:

");

/*输入图的结点数和边数*/

scanf("%d,%d",&p->vexnum,&p->edgenum);

for(i=1;i<=p->vexnum;i++)

{printf("\n\t\t\t请输入结点%d的名称:

",i);/*输入顶点数据信息*/

scanf("%s",p->list[i].data);

p->list[i].fistedge=NULL;/*初始化指针*/

}

for(k=0;kedgenum;k++)/*输入各边并构造多重链表*/

{printf("\n\t\t\t请输入互相有关联的两个结点:

");

scanf("%d,%d",&i,&j);

q=(EBox*)malloc(sizeof(EBox));

q->mark=0;/*对边结点赋值*/

q->ivex=i;

q->ilink=p->list[i].fistedge;

q->jvex=j;

q->jlink=p->list[j].fistedge;

p->list[i].fistedge=p->list[j].fistedge=q;/*完成边在链头的插入*/

}

printf("\n");

}

voidDFS(AMLGraph*p,intv)

{/*对第v个顶点的深度优先遍历*/

intw;

EBox*q;

visited[v]=1;/*标记已访问结点*/

printf("%s",p->list[v].data);

for(q=p->list[v].fistedge;q!

=NULL;)

{if(q->ivex==v)

{w=q->jvex;q=q->jlink;}

else

{w=q->ivex;q=q->ilink;}

if(!

visited[w])DFS(p,w);/*对尚未访问的点调用DFS*/

}

}

voidDFSTraverse(AMLGraph*p,intn)

{/*深度优先遍历*/

intv;

printf("\n\t\t\t");

for(v=1;v<=p->vexnum;v++)

visited[v]=0;*访问标志数组初始化*/

DFS(p,n);/*对起始顶点调用DFS*/

for(v=1;v<=p->vexnum;v++)

if(!

visited[v])DFS(p,v);/*对尚未访问的顶点调用DFS*/

printf("\n");

}

2、队列类型

typedefintQelemType;

typedefstructQNode{

QElemTypedata;

structQNode*next;

}QNode,*QueuePtr;

typedefstruct{

QueuePtrfront;

QueuePtrrear;/*队头、队尾指针*/

}LinkQueue;

队列的基本操作如下:

StatusInitQueue(LinkQueue&Q);//构造一个空队列Q。

StatusDestroyQueue(LinkQueue&Q);//销毁队列Q(无论空否均可)。

StatusQueueEmpty(LinkQueueQ);//若Q为空队列,则返回1,否则返回-1。

StatusEnQueue(LinkQueue&Q,QElemTypee);//插入元素e为Q的新的队尾元素。

StatusDeQueue(LinkQueue&Q,QElemType&e);//若队列不空,删除Q的队头元素,用e返回其值,并返回1,否则返回-1。

其中部分操作的算法如下:

voidBFS(AMLGraph*p,intv)

{/*对第v个顶点进行广度优先遍历*/

intu,w;

EBox*x;

typedefstructqueue

{

intm;

structqueue*next;

}Q;/*辅助队列Q*/

Q*head,*tail,*q;

head=tail=(Q*)malloc(sizeof(Q));

tail->next=NULL;

visited[v]=1;/*标记已访问结点*/

printf("%s",p->list[v].data);

tail->m=v;/*v入队列*/

tail->next=(Q*)malloc(sizeof(Q));

tail=tail->next;

tail->next=NULL;

while(head!

=tail)

{

q=head;

head=head->next;

u=q->m;/*对头元素出队并置为u*/

free(q);

for(x=p->list[u].fistedge;x!

=NULL;)

{if(x->ivex==u){w=x->jvex;x=x->ilink;}

else{w=x->ivex;x=x->jlink;}

if(!

visited[w])

{

visited[w]=1;

printf("%s",p->list[w].data);

tail->m=w;/*w入队列*/

tail=tail->next=(Q*)malloc(sizeof(Q));

tail->next=NULL;

}/*if*/

}/*for*/

}/*while*/

}/*BFS*/

voidBFSTraverse(AMLGraph*p,intn)

{printf("\n\t\t\t");/*广度优先遍历*/

intv;

for(v=1;v<=p->vexnum;v++)

visited[v]=0;/*访问标志数组初始化*/

BFS(p,n);/*对起始顶点调用BFS*/

for(v=1;v<=p->vexnum;v++)

if(!

visited[v])BFS(p,v);

printf("\n");/*对未访问顶点调用BFS*/

}

3、主程序和其他伪码算法voidmain(){显示菜单;输入功能选择键;switch(flag){case1:

手动构造一个图;case2:

进行深度优先遍历图;case3:

进行广度优先遍历图;case4:

退出程序;}算法代码

intmain()/*主函数*/

{intx,n;

AMLGraphgraph,*p;

p=&graph;

printf("\t\t\t******图的深度和广度优先遍历*******\n");

printf("\t\t\t**\n")

while

(1)

{printf("\n");

printf("\t\t\t~~~~~~~~功能菜单~~~~~~~\n");

printf("\n");

printf("\t\t\t*********************************************\n");

printf("\t\t\t*1.创建图*\n");

printf("\t\t\t**\n");

printf("\t\t\t*2.深度优先遍历图*\n");

printf("\t\t\t**\n");

printf("\t\t\t*3.广度优先遍历图*\n");

printf("\t\t\t**\n");

printf("\t\t\t*4.退出系统*\n");

printf("\t\t\t**\n");

printf("\t\t\t*********************************************\n");

printf("\n\t\t\t请输入选择的功能编号(1-4):

");

scanf("%d",&n);

if(n<0||n>4)

{

printf("\n\n\t\t\t你输入的功能号错误,请重新输入,按Enter键继续!

");

getchar();

getchar();

continue;

}

switch(n)

{

case1:

CreateGraph(p);break;

case2:

{

printf("\n\t\t\t请输入起始遍历结点:

");

scanf("%d",&x);

printf("\n\t\t\t深度优先遍历结果为:

");

printf("\n");

DFSTraverse(p,x);

printf("\n");

}break;

case3:

{

printf("\n\t\t\t请输入起始遍历结点:

");

scanf("%d",&x);

printf("\n\t\t\t广度优先遍历结果为:

");

printf("\n");

BFSTraverse(p,x);

printf("\n");

}break;

case4:

printf("\n\n\t\t\t谢谢你的使用!

\n\n\n");

exit(0);

}/*switch*/

}/*while*/

return0;

}/*main*/

四、调试分析1、本程序以邻接多重表为存储结构。

这个程序涉及到图的生成和图的深度以及广度遍历,文件的保存和读取,还有栈和队列的操作,另外还有森林的生成和打印,路径的寻找。

2、本程序不仅可以进行连通无向图的遍历,还可以进行非连通图的遍历。

为了方便显示和理解,现在暂且用一个大写字母表示一个顶点。

边还可以附加信息,但为了方便操作,暂且不输入信息。

已经先把图的相关信息保存在了文本文档里,所以要测试时直接从文件导入,可以减少用手输入的麻烦,同时也可以减少输入的错误。

3、由于构造图时,后输入的边是插在先输入的边的前面。

所以在输入边时,可以按字母从大到小的顺序输入。

那么显示图的时候就可以按字母从小到大的顺序显示。

4、程序定义了一个二倍顶点长的数组存放输入的边,以便程序可以把它保存到文件里。

故耗费了一定的内存空间。

五、用户手册1、进入演示程序后即显示一个有功能选择的界面,如下:

2、选择操作1:

程序就提示分别输入无向图的顶点数,边数,边的信息,顶点和边的值:

输入完成后,返回菜单。

3、选择操作2:

系统提示输入遍历图的起始点,程序运行后,首先显示深度优先遍历的访问结点序列。

4、选择操作3:

系统提示输入遍历图的起始点,程序运行后,首先显示广度优先遍历的访问结点序列。

5、选择操作4:

退出程序。

六、测试结果

 

附:

源程序

#include

#include

#defineMAX_VERTEX_NUM30/*无向图最大顶点数*/

#defineMAX_LEN20/*数据最大长度*/

intvisited[MAX_VERTEX_NUM];/*全局变量,访问标志数组*/

typedefstructEBox/*边结点类型*/

{

intmark;/*访问标记*/

intivex,jvex;/*该边依附的两个顶点位置*/

structEBox*ilink,*jlink;/*分别指向依附这两个顶点的下一条边*/

}EBox;

typedefstructVexBox/*顶点结点类型*/

{

chardata[MAX_LEN];

EBox*fistedge;/*指向第一条依附该顶点的边*/

}VexBox;

typedefstruct

{

VexBoxlist[MAX_VERTEX_NUM];

intvexnum,edgenum;/*无向图当前顶点数和边数*/

}AMLGraph;

voidCreateGraph(AMLGraph*p)/*创建无向图*/

{

inti,j,k;

EBox*q;

printf("\n\t\t\t请输入图的结点个数和边的个数:

");/*输入图的结点数和边数*/

scanf("%d,%d",&p->vexnum,&p->edgenum);

for(i=1;i<=p->vexnum;i++)

{printf("\n\t\t\t请输入结点%d的名称:

",i);/*输入顶点数据信息*/

scanf("%s",p->list[i].data);

p->list[i].fistedge=NULL;/*初始化指针*/

}

for(k=0;kedgenum;k++)/*输入各边并构造多重链表*/

{printf("\n\t\t\t请输入互相有关联的两个结点:

");

scanf("%d,%d",&i,&j);

q=(EBox*)malloc(sizeof(EBox));

q->mark=0;/*对边结点赋值*/

q->ivex=i;

q->ilink=p->list[i].fistedge;

q->jvex=j;

q->jlink=p->list[j].fistedge;

p->list[i].fistedge=p->list[j].fistedge=q;/*完成边在链头的插入*/

}

printf("\n");

}

voidDFS(AMLGraph*p,intv)

{/*对第v个顶点的深度优先遍历*/

intw;

EBox*q;

visited[v]=1;/*标记已访问结点*/

printf("%s",p->list[v].data);

for(q=p->list[v].fistedge;q!

=NULL;)

{if(q->ivex==v)

{w=q->jvex;q=q->jlink;}

else

{w=q->ivex;q=q->ilink;}

if(!

visited[w])DFS(p,w);/*对尚未访问的点调用DFS*/

}

}

voidDFSTraverse(AMLGraph*p,intn)

{/*深度优先遍历*/

intv;

printf("\n\t\t\t");

for(v=1;v<=p->vexnum;v++)

visited[v]=0;/*访问标志数组初始化*/

DFS(p,n);/*对起始顶点调用DFS*/

for(v=1;v<=p->vexnum;v++)

if(!

visited[v])DFS(p,v);/*对尚未访问的顶点调用DFS*/

printf("\n");

}

voidBFS(AMLGraph*p,intv)

{/*对第v个顶点进行广度优先遍历*/

intu,w;

EBox*x;

typedefstructqueue

{

intm;

structqueue*next;

}Q;/*辅助队列Q*/

Q*head,*tail,*q;

head=tail=(Q*)malloc(sizeof(Q));

tail->next=NULL;

visited[v]=1;/*标记已访问结点*/

printf("%s",p->list[v].d

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 法律文书 > 判决书

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1