图地深度广度遍历算法与大数据结构课程设计.docx
- 文档编号:29407892
- 上传时间:2023-07-23
- 格式:DOCX
- 页数:21
- 大小:57.25KB
图地深度广度遍历算法与大数据结构课程设计.docx
《图地深度广度遍历算法与大数据结构课程设计.docx》由会员分享,可在线阅读,更多相关《图地深度广度遍历算法与大数据结构课程设计.docx(21页珍藏版)》请在冰豆网上搜索。
图地深度广度遍历算法与大数据结构课程设计
图的操作
一、问题描述
图是一种较线性表和树更为复杂的数据结构。
在图形结构中,节点间的关系可以是任意的,图中任意两个数据元素之间都可以相关。
由此,图的应用极为广泛。
现在邻接矩阵和邻接表的存储结构下,完成图的深度、广度遍历。
二、基本要求
1、选择合适的存储结构完成图的建立;
2、建立图的邻接矩阵,能按矩阵方式输出图,并在此基础上,完成图的深度和广度遍历,输出遍历序列;
3、建立图的邻接表,并在此基础上,完成图的深度和广度遍历,输出遍历序列;
三、测试数据
四、算法思想
1、邻接矩阵
顶点向量的存储。
用两个数组分别存储数据(定点)的信息和数据元素之间的关系(边或弧)的信息。
2、邻接表
邻接表是图的一种链式存储结构。
在邻接表中,对图中每个定点建立一个单链表,第i个单链表中的节点表示依附于定点vi的边。
每个节点由3个域组成,其中邻接点域(adjvex)指示与定点vi邻接的点在图中的位置,链域(nextarc)指示下一条边或弧的节点;数据域(info)存储和边或弧相关的信息,如权值等。
每个链表上附设一个头节点。
在表头节点中,除了设有链域(firstarc)指向链表中第一个节点之外,还设有存储定点vi的名或其他有关信息的数据域(data)。
3、图的深度遍历
深度优先搜索遍历类似于树的先根遍历,是树的先跟遍历的推广。
假设初始状态是图中所有顶点未曾被访问,则深度优先搜索可从图中某个顶点v出发,访问此顶点,然后依次从v的未被访问的邻接点出发深度优先遍历图,甚至图中所有和v相通的顶点都被访问到;若此时图有顶点未被访问,则另选图中一个未曾被访问的顶点作起始点,重复上述过程,直至图中所有顶点都被访问到为止。
4、图的广度遍历
广度优先遍历类似于树的按层次遍历过程。
假设从图中某顶点v出发,在访问了v之后依次访问v的各个未曾访问过的邻接点,然后分别从这些邻接点出发依次访问它们的邻接点,并使“先被访问的顶点的邻接点”先与“后被访问的顶点的邻接点”被访问,直至图中所有已被访问的顶点的邻接点都被访问到。
若此时图有顶点未被访问,则另选图中一个曾被访问的顶点作起始点,重复上述过程,直至图中所有顶点都被访问到为止。
五、模块划分
一、基于邻接矩阵的深广度遍历
1.StatusInitQueue(LinkQueue*Q)
根据已知Q初始化队列
2.StatusQueueEmpty(LinkQueueQ)
判断队列是否为空
3.StatusEnQueue(LinkQueue*Q,QElemTypee)
将e压入队尾
4.StatusDeQueue(LinkQueue*Q,QElemType*e)
取队头元素e
5.intLocateVex(MGraphG,VertexTypev)
定位定点v
6.voidCreateGraph(MGraph*G)
建立无向图的邻接矩阵
7.voidPrintGraph(MGraphG)
输出邻接矩阵的无向图
8.intFirstAdjVex(MGraphG,intv)
第一个邻接点的定位
9.intNextAdjVex(MGraphG,intv,intw)
查找下一个邻接点
10.voidDfs(MGraphG,intv)
实现图的一次遍历
11.voidDfsTraverse(MGraphG)
实现图的深度遍历
12.voidBfsTraverse(MGraphG)
实现图的广度遍历
13.Main
主函数
二、基于邻接表实现图的深广度遍历
1.StatusInitQueue(LinkQueue*Q)
根据已知Q初始化队列
2.StatusQueueEmpty(LinkQueueQ)
判断队列是否为空
3.StatusEnQueue(LinkQueue*Q,QElemTypee)
将e压入队尾
4.StatusDeQueue(LinkQueue*Q,QElemType*e)
取队头元素e
5.voidcreateALGraph(ALGraph*G)
建立无向图的邻接矩阵
6.voidPrintGraph(MGraphG)
输出邻接矩阵的无向图
7.intFirstAdjVex(MGraphG,intv)
第一个邻接点的定位
8.intNextAdjVex(MGraphG,intv,intw)
查找下一个邻接点
9.voidDfs(MGraphG,intv)
实现图的一次深度遍历
10.voidDfsTraverse(MGraphG)
实现图的深度遍历
11.voidBFS(ALGraphG,intv)
实现图的一次广度遍历
12.voidBfsTraverse(MGraphG)
实现图的广度遍历
13.Void…………………………………Main
主函数
六、数据结构//(ADT)
1、基于邻接矩阵的图的类型定义
typedefstructArcCell
{VRTypeadj;/*图中有1/0表示是否有边,网中表示边上的权值*/
/*InfoType*info;与边相关的信息*/
}ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedefstruct
{VertexTypevexs[MAX_VERTEX_NUM];/*顶点向量*/
AdjMatrixarcs;/*邻接矩阵*/
intvexnum,arcnum;/*图中当前顶点数和边数*/
}MGraph;
2、基于邻接表的图的类型定义
typedefstructArcNode
{
intadjvex;
structArcNode*nextarc;
}ArcNode;/*表节点*/
typedefstruct
{
TElemTypedata;
ArcNode*firstarc;
}VNode,AdjList[MAXVER];/*表节点*/
typedefstruct
{
AdjListvertices;
intvexnum,arcnum;/*图中当前顶点数和边数*/
}ALGraph;
七、源程序
一、基于邻接矩阵的图的深度、广度遍历
#include"stdlib.h"
#include"stdio.h"
#include"string.h"
#defineTRUE1
#defineFALSE0
#defineOVERFLOW-2
#defineOK1
#defineERROR0
typedefintStatus;
#defineINFINITYINT_MAX/*最大值“无穷”*/
#defineMAX_VERTEX_NUM20/*最大顶点个数*/
typedefintBoolean;
typedefcharVertexType[20];
typedefintVRType;
/**************以下为队列的操作************/
/****队列的类型定义****/
typedefintQElemType;
typedefstructQNode
{QElemTypedata;
structQNode*next;
}QNode,*QueuePtr;
typedefstruct
{
QueuePtrfront;
QueuePtrrear;
}LinkQueue;
/****初始化队列****/
StatusInitQueue(LinkQueue*Q)
{(*Q).front=(*Q).rear=(QueuePtr)malloc(sizeof(QNode));
if(!
(*Q).front)exit(OVERFLOW);
(*Q).front->next=NULL;
returnOK;}
/****判断队列是否为空****/
StatusQueueEmpty(LinkQueueQ)
{if(Q.front==Q.rear)
returnTRUE;
else
returnFALSE;}
/****入队列****/
StatusEnQueue(LinkQueue*Q,QElemTypee)
{QueuePtrp;
p=(QueuePtr)malloc(sizeof(QNode));
if(!
p)exit(OVERFLOW);
p->data=e;p->next=NULL;
(*Q).rear->next=p;
(*Q).rear=p;
returnOK;}
/****出队列****/
StatusDeQueue(LinkQueue*Q,QElemType*e)
{QueuePtrp;
if((*Q).front==(*Q).rear)returnERROR;
p=(*Q).front->next;
*e=p->data;
(*Q).front->next=p->next;
if((*Q).rear==p)(*Q).rear=(*Q).front;
free(p);
returnOK;}
/**************以下为图的操作************/
/*图的类型定义*/
typedefstructArcCell
{VRTypeadj;/*图中有1/0表示是否有边,网中表示边上的权值*/
/*InfoType*info;与边相关的信息*/
}ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedefstruct
{VertexTypevexs[MAX_VERTEX_NUM];/*顶点向量*/
AdjMatrixarcs;/*邻接矩阵*/
intvexnum,arcnum;/*图中当前顶点数和边数*/
}MGraph;
/*顶点在顶点向量中的定位*/
intLocateVex(MGraphG,VertexTypev)
{inti;
for(i=0;i if(strcmp(v,G.vexs[i])==0)break; returni; } /*建立无向图的邻接矩阵*/ voidCreateGraph(MGraph*G) {inti,j,k;VertexTypev1,v2; printf("\nInputMGvexnum,arcnum: "); scanf("%d,%d",&(*G).vexnum,&(*G).arcnum); printf("Input%dvexs: ",(*G).vexnum); for(i=0;i<(*G).vexnum;i++)/*输入顶点向量*/ {scanf("%s",(*G).vexs[i]);} printf("vexslist\n"); for(i=0;i puts(G->vexs[i]); for(i=0;i<(*G).vexnum;i++)/*邻接矩阵初始化*/ for(j=0;j<(*G).vexnum;j++) (*G).arcs[i][j].adj=0; printf("\nInput%darcs(vivj): \n",(*G).arcnum); for(k=0;k<(*G).arcnum;k++)/*输入无权图的边*/ {scanf("%s%s",v1,v2); i=LocateVex(*G,v1);j=LocateVex(*G,v2); (*G).arcs[i][j].adj=1; (*G).arcs[j][i]=(*G).arcs[i][j]; } } /*按邻接矩阵方式输出无向图*/ voidPrintGraph(MGraphG) {inti,j; printf("\nMGraph: \n"); for(i=0;i {printf("%10s",G.vexs[i]); for(j=0;j printf("%4d",G.arcs[i][j].adj); printf("\n"); } } /*查找第1个邻接点*/ intFirstAdjVex(MGraphG,intv) {intj,p=-1; for(j=0;j if(G.arcs[v][j].adj==1){p=j;break;} returnp; } /*查找下一个邻接点*/ intNextAdjVex(MGraphG,intv,intw) {intj,p=-1; for(j=w+1;j if(G.arcs[v][j].adj==1){p=j;break;} returnp; } /*深度遍历*/ Booleanvisited[MAX_VERTEX_NUM];/*设置全局的访问标志数组*/ voidDfs(MGraphG,intv) {intw; visited[v]=TRUE; printf("%s",G.vexs[v]); for(w=FirstAdjVex(G,v);w>=0;w=NextAdjVex(G,v,w)) if(! visited[w])Dfs(G,w); } voidDfsTraverse(MGraphG) {intv; for(v=0;v visited[v]=FALSE; for(v=0;v if(! visited[v])Dfs(G,v); } /*广度遍历*/ voidBfsTraverse(MGraphG) {intv,u,w;LinkQueueQ; for(v=0;v InitQueue(&Q); for(v=0;v if(! visited[v]) {visited[v]=TRUE; printf("%s",G.vexs[v]); EnQueue(&Q,v); while(! QueueEmpty(Q)) {DeQueue(&Q,&u); for(w=FirstAdjVex(G,u);w>=0;w=NextAdjVex(G,u,w)) if(! visited[w]) {visited[w]=TRUE; printf("%s",G.vexs[w]); EnQueue(&Q,w); } } } } /*主函数*/ main() {intw; MGraphG; CreateGraph(&G); PrintGraph(G); printf("\nDfs: ");DfsTraverse(G);/*深度遍历*/ printf("\nBfs: ");BfsTraverse(G);/*广度遍历*/ } 二: 基于邻接表的图的深度、广度遍历 #include"stdlib.h" #include"stdio.h" #include"string.h" #defineMAXVER21 #defineN100 typedefcharTElemType[10]; /*循环队列的操作*/ /****队列的类型定义****/ typedefintElemType; typedefstruct { ElemType*base; intfront,rear; }SqQueue; /****初始化队列****/ voidInitQueue(SqQueue*Q) {Q->base=(ElemType*)malloc(N*sizeof(ElemType)); Q->front=Q->rear=0;} /****判断队列是否为空****/ intQueueEmpty(SqQueueQ) {if(Q.front==Q.rear) return1; else return0;} /****入队列****/ intEnQueue(SqQueue*Q,ElemTypee) {if((Q->rear+1)%N==Q->front) return0; Q->base[Q->rear]=e; Q->rear=(Q->rear+1)%N; return1;} /****出队列****/ intDeQueue(SqQueue*Q,ElemType*e) {if(Q->rear==Q->front) return0; *e=Q->base[Q->front]; Q->front=(Q->front+1)%N; return1;} /*图的操作*/ /*图的类型定义*/ typedefstructArcNode { intadjvex; structArcNode*nextarc; }ArcNode; typedefstruct { TElemTypedata; ArcNode*firstarc; }VNode,AdjList[MAXVER]; typedefstruct { AdjListvertices; intvexnum,arcnum; }ALGraph; /*建立无向图的邻接矩阵*/ voidcreateALGraph(ALGraph*G) { inti,s,d; ArcNode*p,*q; printf("\nInputMGvexnum,arcnum: "); scanf("%d,%d",&(*G).vexnum,&(*G).arcnum); for(i=1;i<=G->vexnum;i++) { printf("\n输入第%d个顶点信息: ",i); scanf("%s",G->vertices[i].data); G->vertices[i].firstarc=NULL; }//输入第i个结点值并初始化第i个单链表为空 for(i=1;i<=G->arcnum;i++) { printf("\n输入第%d条边的始点和终点: ",i); scanf("%d,%d",&s,&d); p=(ArcNode*)malloc(sizeof(ArcNode)); p->adjvex=d; p->nextarc=G->vertices[s].firstarc; G->vertices[s].firstarc=p; //将新建的以d为信息的表结点p插入s单链表的头结点后 q=(ArcNode*)malloc(sizeof(ArcNode)); q->adjvex=s; q->nextarc=G->vertices[d].firstarc; G->vertices[d].firstarc=q; //将新建的以s为信息的表结点q插入d单链表的头结点后 } } /*深度遍历*/ intvisited[MAXVER];//定义全局数组遍历visited voiddfs(ALGraphG,intv)//被遍历的图G采用邻接表作为存储结构,v为出发顶点编号 { ArcNode*p; printf("%s",G.vertices[v].data); visited[v]=1; p=G.vertices[v].firstarc; while(p! =NULL) { if(visited[p->adjvex]==0)dfs(G,p->adjvex); //若p所指表结点对应的邻接顶点未访问则递归地从该顶点出发调用dfs p=p->nextarc; } } voiddfsTraverse(ALGraphG) { intv; //遍历图之前初始化各未访问的顶点 for(v=1;v<=G.vexnum;v++) visited[v]=0; //从各个未被访问过的顶点开始进行深度遍历 for(v=1;v<=G.vexnum;v++) if(visited[v]==0)dfs(G,v); } /*广度遍历*/ voidBFS(ALGraphG,intv) //从顶点编号v出发,广度遍历邻接表存储的图G { SqQueueQ;ArcNode*p; InitQueue(&Q); printf("%s",G.vertices[v].data); visited[v]=1; EnQueue(&Q,v); while(! QueueEmpty(Q)) { v=DeQueue(&Q,&v); p=G.vertices[v].firstarc; while(p! =NULL) { if(visited[p->adjvex]==0) { v=p->adjvex; printf("%s",G.vertices[v].data); visited[v]=1; EnQueue(&Q,v); } p=p->nextarc; } } } voidBFSTraverse(ALGraphG) { intv; //遍历G以前,初始化visited数组为0 for(v=1;v<=G.vexnum;v++) visited[v]=0; for(v=1;v<=G.vexnum;v++) if(visited[v]==0) BFS(G,v); } voidmain() { ALGraphG; createALGraph(&G); printf("深度遍历结果为: \n"); dfsTraverse(G); printf("\n广度遍历结果为: \n"); BFSTraverse(G); system("pause"); } 八、测试情况 程序的测试结果如下: 1、基于邻接矩阵的图的深度、广度遍历 结果正确 2、基于邻接表的图的深度、广度遍历 结果正确 九、参考文献 1、严蔚敏,《数据结构C语言》,清华大学。 2、谭浩强,《c语言程序设计》,清华大学。 小结 图的遍历是有关于图的算法中最常见、最典型的算法。 与树的遍历相类似,图的遍历是从图中任意
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 深度 广度 遍历 算法 数据结构 课程设计