图的遍历和生成树求解实现的课程结构设计
图的遍历和生成树求解说明书Word版
*******************实践教学*******************兰州理工大学计算机与通信学院2012年春季学期算法与数据结构课程设计题目:______________专业班级:_______________姓名:_______________学号:指导教师:李睿成绩:_______________目录摘要 (2)1.采用类C语言定义相关数据类型 (2)2.各模块流程图及伪码算法 (3)3.函数的调用关系图 (10)4.调试分析 (11)5.测试结果 (12)6.源程序(见附录) (18)设计总结 (19)参考文献 (20)致谢 (20)附件Ⅰ任务一源程序代码 (21)摘要很多涉及图上操作的算法都是以图的遍历操作为基础的,该设计要求写一个程序,演示出图遍历的过程,并给出图的生成树(网的最小代价生成树)。
通过该题目的设计过程,可以加深理解图数据结构及队列的逻辑结构、存储结构及图的深度优先和广度优先遍历过程,掌握图数据据结构上基本运算的实现,进一步理解和熟练掌握课本中所学的各种数据结构,学会如何把学到的知识用于解决实际问题,培养动手能力。
关键字:图;深度优先遍历;广度优先遍历;生成树1.采用类C语言定义相关数据类型图存储结构的定义:1)顺序存储(邻接矩阵)#define MAX_VERTEX_NUM 30 //最大顶点个数Typedef enum{DG,DN,UDG,UDN} GraphKind; //图的种类:有向图、有向网、无向图、无向网ArcTypeAdjMtrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; //ArcType 是顶点关系类型,对无权图,用0和1表示是否相邻,对于网,则为权值类型typedef struct {VertexType vex[MAX_VERTEX_NUM]; //顶点数组AdjMtrix arc; //邻接矩阵int vexnum,arcnum; //图中的顶点数和边数GraphKind kind; //图的种类}GraphMtrix;(2)邻接表的存储#define MAX_VERTEX_NUM 30 //最大顶点个数typedef struct EdgeNode{ //表结点int adjvex; //边或弧依赖的顶点序号InfType *info; //弧或边的相关信息,在网中则为权值struct EdgeNode *next;}EdgeNode;typedef struct VexNode{ //顶点元素VertexType vextex;EdgeNode *link;}VexNode,AdjList[MAX_VERTEX_NUM];typedef struct{ //邻接表AdjList vertices;int vexnum,arcnum; //图中的顶点数和边数GraphKind kind; //图的种类} AdjListGrap2.各模块流程图及伪码算法(1) 遍历算法a.深度优先遍历void DFS(AdjListGraph G,int v)//图G采用邻接表存储结构,v是遍历起始点在邻接表中的下标值,其下标从0开始{visited[v]=1; //置已访问标志visite(G.vertices[v].vextex); //访问顶点for (p = G.vertices[v].link; p; p = p->next)if (!visited[p->adjvex])DFS(G,p->adjvex);//当前顶点未访问,继续深度优先遍历} // DFSb.广度优先遍历void BFS(AdjListGrap G,intv)//图G采用邻接表存储结构,v是遍历起始点在邻接表中的下标,邻接表中下标从0开始,以队列作为基本辅助数据结构{InitQueue(Q); //初始化队列Qvisited[v]=1; //置已访问标志visite(G.vertices[v]. vextex); //访问顶点EnQueue(Q,v); //被访问顶点入队while (!QueueEmpty(Q)){DeQueue(Q,v); //出队列for (p = G.vertices[v].link; p; p = p->next) //找所有和v相邻接的顶点if (!visited[p->adjvex]){visited[p->adjvex]=1;visite(G.vertices [p->adjvex].vextex);EnQueue(Q,p->adjvex);} //if} //while} // BFS(2)流程图a.深度优先遍历dfstrab.广度优先遍历Bfstrac.Prim算法(3) 程序的伪代码算法:a.广度优先遍历:void dfstra (MGraph *G,int i){ /*以vi为出发点对邻接矩阵表示的图G进行DFS搜索,设邻接矩阵是0,l矩阵*/整型 j;打印 ("visit vertex:%c",G->vexs[i]);/*访问顶点vi*/ visited[i]=TRUE;for(j=0;j<G->n;j++) /*依次搜索vi的邻接点*/if(G->edges[i][j]==1&&!visited[j])DFSM(G,j)/*(vi ,vj)∈E,且vj未访问过,故vj为新出发点}DFSM*/说明:对于具有n个顶点和e条边的无向图或有向图,遍历算法DFSTraverse对图中每顶点至多调用一次DFS或DFSM。
数据结构课程设计-图的遍历和构建
摘要图(Graph)是一种复杂的非线性结构。
图可以分为无向图、有向图。
若将图的每条边都赋上一个权,则称这种带权图网络。
在人工智能、工程、数学、物理、化学、计算机科学等领域中,图结构有着广泛的应用。
在图结构中,对结点(图中常称为顶点)的前趋和后继个数都是不加以限制的,即结点之间的关系是任意的。
图中任意两个结点之间都可能相关。
图有两种常用的存储表示方法:邻接矩阵表示法和邻接表表示法。
在一个图中,邻接矩阵表示是唯一的,但邻接表表示不唯一。
在表示的过程中还可以实现图的遍历(深度优先遍历和广度优先遍历)及求图中顶点的度。
当然对于图的广度优先遍历还利用了队列的五种基本运算(置空队列、进队、出队、取队头元素、判队空)来实现。
这不仅让我们巩固了之前学的队列的基本操作,还懂得了将算法相互融合和运用。
目录第一章课程设计目的..................................................................................... 错误!未定义书签。
第二章课程设计内容和要求....................................................................... 错误!未定义书签。
2.1课程设计内容.................................................................................. 错误!未定义书签。
2.1.1图的邻接矩阵的建立与输出ﻩ错误!未定义书签。
2.1.2图的邻接表的建立与输出............................................... 错误!未定义书签。
2.1.3图的遍历的实现.................................................................... 错误!未定义书签。
图的遍历及生成树
• •邻接表的DFS算法
void DFS(ALGraph G, int v) { ArcNode *p;
visited[v] = 1; /*置已访问标记*/ printf("%d ", v); /*输出被访问顶点的编号*/ p = G.vertices[v].firstarc; /*p指向顶点v的第一个邻接点*/ while (p!=NULL) {
•v11
•v1,
•v2
•v3
•v2,
•v4,
•v5
•v8,
•v4
•v6
•v7
•v5,
•v3,
•v8
•v6,
•v7
•
•图的DFS算法一般描述
•int visited[MAXVEX]; //访问标志数组
•void DFSTraverse(Graph G)
•{ //对图G作深度优先遍历
• for( v=0; v<G.vexnum; ++v ) visited[v]=FALSE;
•} // DFS1
•G.arcs[v][j] =1
•有邻接点
•visited [n]=0
•未访问过
•
分析:
在遍历图时,对图中每个顶点至多调用一次DFS函数 ,因为一旦某个顶点被标志成已被访问,就不再从它出发 进行搜索。
因此,遍历图的过程实质上是对每个顶点查找其邻接 点的过程。其耗费的时间则取决于所采用的存储结构。 如果用邻接矩阵来表示图,遍历图中每一个顶点都要从 头扫描该顶点所在行,因此遍历全部顶点所需的时间为 O(n2)。 如果用邻接表来表示图,虽然有 2e 个表结点,但只需扫 描 e 个结点即可完成遍历,加上访问 n个头结点的时间, 因此遍历图的时间复杂度为O(n+e)。
图的遍历及生成树.ppt
• 每当到达一个其所相邻接的顶点都已被访问过的 顶点,则从最后所访问的顶点开始,依次退回到尚 有邻接顶点末曾访问过的顶点u,并从u开始进行 深序优先搜索…..
• 直到所有顶点都访问过或从任何一个已访问过的 顶点出发,再也无法到达末曾访问过的顶点
int ver2;} E_NODE; L_NODE *head[MAXN]; int visit[MAXN]; E_NODE e[MAXN]; int n,m,u;
void creat_adj_list(head,n,e,m) L_NODE *head[ ]; E_NODE e[ ]; int n,m; {int i,u,v; L_NODE *p; for (i=1;i<=n;i++) head[i]=NULL; for(i=0;i<m;i++) { u=e[i].ver1; v=e[i]=ver2; p=(L_NODE*)moalloc(sizeof(L_NODE)); p->ver=v; p->link=head[u];head[u]=p; p=(L_NODE*)moalloc(sizeof(L_NODE)); p->ver=u; p->link=head[v];head[v]=p;} }
}
求图的连通分量
• 对图的每一个顶点进行检验
– 若被访问过,则该顶点落在已被求出的连通分 量上
– 若末被访问过,则从该顶点出发遍历图,便可 求得图的另一个连通分量
生成树和最小生成树
• 生成树:
设G是一个连通无向图,若G’是包含G中所有 顶点的一个无回路的连通子图,则称G’是G的一棵 生成树
数据结构与算法课程设计报告---图的算法实现
数据结构与算法课程设计报告课程设计题目:图的算法实现专业班级:信息与计算科学1002班目录摘要 (1)1、引言 (1)2、需求分析 (1)3、概要设计 (2)4、详细设计 (4)5、程序设计 (10)6、运行结果 (18)7、总结体会 (19)摘要(题目): 图的算法实现实验内容图的算法实现问题描述:(1)将图的信息建立文件;(2)从文件读入图的信息,建立邻接矩阵和邻接表;(3)实现Prim、Kruskal、Dijkstra和拓扑排序算法。
关键字:邻接矩阵、Dijkstra和拓扑排序算法1.引言本次数据结构课程设计共完成图的存储结构的建立、Prim、Kruskal、Dijkstra 和拓扑排序算法等问题。
通过本次课程设计,可以巩固和加深对数据结构的理解,通过上机和程序调试,加深对课本知识的理解和熟练实践操作。
(1)通过本课程的学习,能够熟练掌握数据结构中图的几种基本操作;(2)能针对给定题目,选择相应的数据结构,分析并设计算法,进而给出问题的正确求解过程并编写代码实现。
使用语言:CPrim算法思想:从连通网N={V,E}中的某一顶点v0出发,选择与它关联的具有最小权值的边(v0,v),将其顶点加入到生成树的顶点集合V中。
以后每一步从一个顶点在V中,而另一个顶点不在V中的各条边中选择权值最小的边(u,v),把它的顶点加入到集合V中。
如此继续下去,直到网中的所有顶点都加入到生成树顶点集合V中为止。
拓扑排序算法思想:1、从有向图中选取一个没有前驱的顶点,并输出之;2、从有向图中删去此顶点以及所有以它为尾的弧;重复上述两步,直至图空,或者图不空但找不到无前驱的顶点为止。
没有前驱-- 入度为零,删除顶点及以它为尾的弧-- 弧头顶点的入度减1。
2.需求分析1、通过键盘输入建立一个新的有向带权图,建立相应的文件;2、对建立的有向带权图进行处理,要求具有如下功能:(1)用邻接矩阵和邻接表的存储结构输出该有向带权图,并生成相应的输出结果;(2)用Prim、Kruskal算法实现对图的最小生成树的求解,并输出相应的输出结果;(3)用Dijkstra算法实现对图中从某个源点到其余各顶点的最短路径的求解,并输出相应的输出结果;(4)实现该图的拓扑排序算法。
实验三图的遍历生成树
实验三图的遍历生成树
实验项目:图的遍历生成树
实验类型: 验证性
实验目的:
1.熟悉图结构
2.掌握图结构上的各种操作
3.学会运用图结构求解问题
涉及的知识点:图的表示法、生成树的概念、图的深度优先、广度优先遍历算法,拓扑排序、最短路径和关键路径
实验内容:
编写程序实现对下图的先深、先广遍历
具体要求:
1. 使用图的邻接矩阵表示法进行编程
2. 实现如下基本接口
FirstAdj(v): 找到编号为v的顶点的第一个邻接顶点
NextAdj(v,w): 设w是v的邻接顶点, 找到v的排在w后的下一个邻接顶点. DepthFirstSearch(v) 对连通图从顶点v开始进行深度优先访问
BreadthFirstSearch(v) 对连通图从顶点v开始进行广度优先访问
实验报告的书写:
实验原理:编写源程序的方法、依据
实验过程原始记录:打印与自己编写的源代码关键的程序段,附加注解
实验结果及分析:打印屏幕输入、输出结果。
注意:除了从顶点1出发之外,再选择另一个结点,即打印两组测试数据(均使用上面指定输入的图)。
数据结构图的遍历实验报告doc
数据结构图的遍历实验报告篇一:【数据结构】图的存储和遍历实验报告《数据结构B》实验报告系计算机与电子专业级班姓名学号XX年1 0 月9日1. 上机题目:图的存储和遍历2. 详细设计#include#define GRAPHMAX 10#define FALSE 0#define TRUE 1#define error printf#define QueueSize 30typedef struct{char vexs[GRAPHMAX];int edges[GRAPHMAX][GRAPHMAX];int n,e;}MGraph;int visited[10];typedef struct{int front,rear,count;int data[QueueSize];}CirQueue;void InitQueue(CirQueue *Q) {Q->front=Q->rear=0;Q->count=0;}int QueueEmpty(CirQueue *Q){return Q->count=QueueSize;}int QueueFull(CirQueue *Q){return Q->count==QueueSize;}void EnQueue(CirQueue *Q,int x) { if(QueueFull(Q)) error("Queue overflow");文档来源为:从网络收集整理.word 版本可编辑.欢迎下载支持else{ Q->count++;Q->data[Q->rear]=x;Q->rear=(Q->rear+1)%QueueSize;}}int DeQueue(CirQueue *Q){int temp;if(QueueEmpty(Q)){ error("Queue underflow");return NULL;}else{ temp=Q->data[Q->front]; Q->count--;Q->front=(Q->front+1)%QueueSize;return temp;}}void CreateMGraph(MGraph *G){int i,j,k;char ch1,ch2;printf("\n\t\t 请输入定点数,边数并按回车 (格式如:3,4):");scanf("%d,%d", &(G->n),&(G->e));for(i=0;in;i++){ getchar();printf("\n\t\t 请输入第%d个定点数并按回车:",i+1);scanf("%c",&(G->vexs[i]));}for(i=0;in;i++)for(j=0;jn;j++)G->edges[i][j]=0;for(k=0;ke;k++){ getchar();printf("\n\t\t 请输入第%d条边的顶点序号 (格式如:i,j ):",k+1);scanf("%c,%c",&ch1,&ch2);for(i=0;ch1!=G->vexs[i];i++);for(j=0;ch2!=G->vexs[j];j++);G->edges[i][j]=1;}}void DFSM(MGraph *G,int i){int j;printf("\n\t\t 深 度 优 列: %c\n",G->vexs[i]);visited[i]=TRUE;for(j=0;jn;j++)if(G->edges[i][j]==1 &&////////////////DFSM(G,j);} void BFSM(MGraph *G,int k){ int i,j;CirQueue Q;InitQueue(&Q);printf("\n\t\t 广 度 优列: %c\n",G->vexs[k]);visited[k]=TRUE;EnQueue(&Q,k); while(!QueueEmpty(&Q)){ i=DeQueue(&Q);先遍历序 visited[j]!=1)先遍历序for(j=0;jn;j++)if(G->edges[i][j]==1 && visited[j]!=1) { visited[j]=TRUE;EnQueue(&Q,j);}}}void DFSTraverseM(MGraph *G) {int i;for(i=0;in;i++)visited[i]=FALSE;for(i=0;in;i++)if(!visited[i]) DFSM(G,i);}void BFSTraverseM(MGraph *G) {int i;for(i=0;in;i++) visited[i]=FALSE;for(i=0;in;i++)if(!visited[i]) BFSM(G,i);}void main(){MGraph *G,a;char ch1;int i,j,ch2;G=&a;printf("\n\t\t 建立一个有向图的邻接矩阵表示\n"); CreateMGraph(G);printf("\n\t\t 已建立一个有向图的邻接矩阵存储\n"); for(i=0;in;i++){ printf("\n\t\t");for(j=0;jn;j++)printf("%5d",G->edges[i][j]);}getchar();ch1='y';while(ch1=='y'||ch1=='Y'){ printf("\n");printf("\n\t\t 图的存储与遍历");("\n\t\t** ******************************");printf("\n\t\t*1 ---- 更新邻接矩阵*"); printf("\n\t\t*2 ---- 深度优先遍历*"); printf("\n\t\t*3 ---- 广度优先遍历*"); printf("\n\t\t*0 ---- 退出*");printf("\n\t\t** ******************************");}} printf("\n\t\t 请选择菜单号 ( 0 ---------------- 3) "); scanf("%d",&ch2); getchar(); switch(ch2) { case1:CreateMGraph(G); printf("\n\t\t 图的邻接矩阵存储建立完成\n");break; case 2:DFSTraverseM(G);break; case3:BFSTraverseM(G);break; case 0:ch1='n';break;default:printf("\n\t\t 输出错误!清重新输入!"); }3. 调试分析(1)调试过程中主要遇到哪些问题?是如何解决的?由于实习之初对邻接表的存储结构了解不是很清楚,所以在运行出了一个小错误,即在输出邻接表时,每个结点都少了一个邻接点。
数据结构40-图的遍历和生成树.
3﹑深度优先遍历生成树 图的所有顶点加上遍历中经过的边所构成的子图叫图的 生成树。
3﹑深度优先遍历算法分析 对于连通图,在dfstravel函数中只要调用一次dfs, 即可遍历图中所有顶点。对于非连通图,有几个连 通分量,则调用几次。由此,也知道了如何求连通 分量的个数。 当用二维数组表示邻接矩阵作图的存储结构时,查 找每个顶点的邻接点所需时间为O(n2),其中n为图 中顶点数。 而当以邻接表作图的存储结构时,找邻接点所需时 间为O(e),其中e为无向图的边数或有向图的弧数。 由此,当以邻接表作存储结构时,深度优先遍历图的时 间复杂度为0(n+e)。
数
据
结
Hale Waihona Puke 构第四十课 图的遍历和生成树
第三十二课 图的遍历和生成树
本课主题:图的遍历和生成树的概念 教学目的:图的遍历和生成树的概念 教学重点:深度优先遍历﹑宽度优先遍历和生成树的概念 教学难点:深度优先遍历﹑宽度优先遍历和生成树的概念 授课内容:
一﹑图的遍历
图的遍历指,从图的某顶点出发,访问图的各顶点,使 每个顶点被访问一次,且只被访问一次。访问的含义可 以是输出个顶点的值,查询顶点,修改顶点等等。 为了遍历方便,设辅助数组visited,初始时,数组元素 的值均为0或false,表示未被遍历,一旦遍历,就置为1 或true。
1﹑深度优先遍历 深度优先遍历的思想 在图中从任意一个顶点(设为v0)开始,进行遍历, 接着找v0的第一邻接点,若该邻接点未被遍历,则 遍历之, 再找该邻接点的第一邻接点, 若该第一邻接点已被遍历,则找其下一邻接点。 若下一邻接点未被遍历,则遍历,再找它的第一邻 接点
就这样递归向下进行。若遇到第一邻接点不存在,或 下一邻接点也不存在时,则退回到调用的上一层。 如此下去,若不能 遍历完所有顶点(说 明不是连通图),则 再选一个未遍历的顶 点,重新开始以上过 程,直至所有顶点遍 历完毕。
(完整版)数据结构详细教案——图
数据结构教案第七章图第7章图【学习目标】1.领会图的类型定义。
2.熟悉图的各种存储结构及其构造算法,了解各种存储结构的特点及其选用原则。
3.熟练掌握图的两种遍历算法。
4.理解各种图的应用问题的算法.【重点和难点】图的应用极为广泛,而且图的各种应用问题的算法都比较经典,因此本章重点在于理解各种图的算法及其应用场合。
【知识点】图的类型定义、图的存储表示、图的深度优先搜索遍历和图的广度优先搜索遍历、无向网的最小生成树、最短路径、拓扑排序、关键路径【学习指南】离散数学中的图论是专门研究图性质的一个数学分支,但图论注重研究图的纯数学性质,而数据结构中对图的讨论则侧重于在计算机中如何表示图以及如何实现图的操作和应用等.图是较线性表和树更为复杂的数据结构,因此和线性表、树不同,虽然在遍历图的同时可以对顶点或弧进行各种操作,但更多图的应用问题如求最小生成树和最短路径等在图论的研究中都早已有了特定算法,在本章中主要是介绍它们在计算机中的具体实现。
这些算法乍一看都比较难,应多对照具体图例的存储结构进行学习。
而图遍历的两种搜索路径和树遍历的两种搜索路径极为相似,应将两者的算法对照学习以便提高学习的效益。
【课前思考】1。
你有没有发现现在的十字路口的交通灯已从过去的一对改为三对,即每个方向的直行、左拐和右拐能否通行都有相应的交通灯指明。
你能否对某个丁字路口的6条通路画出和第一章绪论中介绍的”五叉路口交通管理示意图”相类似的图?2。
如果每次让三条路同时通行,那么从图看出哪些路可以同时通行?同时可通行的路为:(AB,BC,CA),(AB,BC,BA),(AB,AC,CA),(CB,CA,BC)目录第7章图 (1)7.1图的定义和基本术语 (1)7.2图的存储和创建 (2)7.2.1 图的存储表示 (2)7。
2.2 图的创建 (5)7。
3图的遍历 (5)7。
3.1 深度优先搜索 (5)7.3.2 广度优先搜索 (6)7。
4遍历算法的应用 (8)7.4。
数据结构图的遍历课程设计报告书
课程设计报告课程名称数据结构课题名称图的遍历专业网络工程班级学号姓名指导教师陈淑红、张晓清、黄哲2015年 6 月25 日湖南工程学院课程设计任务书课程名称数据结构课题图的遍历专业班级网络工程学生姓名学号指导老师陈淑红、张晓清、黄哲审批任务书下达日期2015 年 3 月 1 日任务完成日期2015 年6月25 日目录一、设计内容与设计要求 (2)1.1设计内容---------------------------------------------------------------------------------------2 1.2选题方案---------------------------------------------------------------------------------------2 1.3设计要求---------------------------------------------------------------------------------------21.4进度安排---------------------------------------------------------------------------------------5二、需求分析 (5)2.1程序功能---------------------------------------------------------------------------------------52.2输入输出要求---------------------------------------------------------------------------------5三、概要设计 (5)3.1流程图------------------------------------------------------------------------------------------5 3.2数据结构---------------------------------------------------------------------------------------63.3函数的调用关系图,主要函数的流程---------------------------------------------------9四、详细设计 (14)4.1定义图------------------------------------------------------------------------------------------14 4.2自动生成无向图------------------------------------------------------------------------------14 4.3手动生成无向图------------------------------------------------------------------------------16 4.4广度优先遍历---------------------------------------------------------------------------------174.5深度优先遍历---------------------------------------------------------------------------------20五、调试运行 (22)5.1 测试数据--------------------------------------------------------------------------------------22 5.2运行程序---------------------------------------------------------------------------------------22 5.3自动生成图操作------------------------------------------------------------------------------235.4手动生成图操作------------------------------------------------------------------------------26六、心得体会 (29)七、源代码 (29)八、评分表 (38)第一章设计内容与设计要求1.1设计内容1.1.1 算术24游戏演示由系统随机生成4张扑克牌,用户利用扑克牌的数字及运算符号“+”、“—”、“*”、“/”及括号“(”和“)”从键盘上输入一个计算表达式,系统运行后得出计算结果,如果结果等于24,则显示“Congratulation!”,否则显示“Incorrect!”设计思路:从键盘输入中缀表达式,然后将中缀表达式转换为后缀表达式,利用后缀表达式求值。
课程设计树、图及其应用
第 3 阶段导学
课程设计3:树、图及其应用
【目的】树和图是两种非线性数据结构,通过本次课程设计,熟悉它们的特性,应用树和图解决具体问题。
【内容】
1、二叉树的建立和遍历的演示
问题描述:建立一棵二叉树,并对其进行遍历(先序、中序、后序),打印输出遍历结果。
基本要求:从键盘输入二叉树的扩展先序序列,建立二叉树的二叉链表存储结构,然后采用递归算法对其进行遍历(先序、中序、后序),并将遍历结果打印输出。
2、图遍历的演示
问题描述:很多涉及图上操作的算法都是以图的遍历操作为基础的。
试写一个程序,演示无向图的遍历操作。
基本要求:以邻接表为存储结构,实现连通无向图的深度优先和广度优先遍历。
以用户指定的结点为起点,分别输出每种遍历下的结点访问序列和相应生成树的边集。
数据结构课程设计报告模板_图的遍历分解
数据结构课程设计报告书设计题目图遍历的演示姓名专业班级学号指导教师成绩评语2014年6月20日目录目录 (1)一、功能需求 (2)(一)原始数据 (2)(二)系统功能 (2)三、程序总体设计 (2)(一)数据结构 (2)(二) 函数原形清单 (3)(三)程序总体框架 (4)(四)详细代码 (4)四、程序清单 (15)五、总结 (18)一、功能需求以邻接多重表为存储结构,实现连通无向图的深度优先和广度优先遍历。
以用户指定的顶点为起点,分别输出每种遍历下的顶点访问序列和相应生成树的边集。
二、系统功能和原始数据(一)原始数据设图的顶点不超过20个,每个顶点用一个编号表示(如果一个图有n个顶点,则它们的编号分别为1,2,…,n)。
通过输入图的全部边输入一个图,每条边为一对整数,可以对边的输入顺序作某种限制。
注意,生成树的边是有向边,端点顺序不能颠倒。
(二)系统功能1.创建无向图2.打印无向图3.深度优先搜索4.广度优先搜索三、程序总体设计(一)数据结构typedef struct EBox{int mark;//访问标记,1代表已访问,0代表未访问int ivex,jvex;//该边依附的两个顶点的位置struct EBox *ilink,*jlink;//分别指向依附这两个顶点的下一条边//InfoType *info;//该边信息指针}EBox;typedef struct VexBox{VertexType data;EBox *firstedge;//指向第一条依附该顶点的边}VexBox;typedef struct{VexBox adjmulist[NUM];int vexnum,edgenum;//无向图的当前顶点数和边数}AMLGraph;//---------------------------------------------------队列的定义typedef int QElemType;typedef struct QNode{QElemType data;struct QNode *next;}QNode,*QueuePtr;typedef struct{QueuePtr front,rear;}LinkQueue;(二) 函数原形清单int LocateVex(AMLGraph G,VertexType u)//寻找输入的数据在图中的位置,若不存在则返回-1int CreateGraph(AMLGraph &G)//采用邻接多重表存储表示,构造无向图GVertexType* GetVex(AMLGraph G,int v) //返回V的值int FirstAdjVex(AMLGraph G,VertexType v)//返回V的第一个邻接点的序号,若没有则返回-1int NextAdjVex(AMLGraph G,VertexType v,VertexType w)//返回V的(相对于W)的下一个邻接结点的序号,若W是V的最后一个邻接结点,则返回-1void DFS(AMLGraph G,int v)//深度优先搜索//深度优先遍历图void DFSTraverse(AMLGraph G,int(*Visit)(VertexType))int InitQueue(LinkQueue *Q) //队列的初始化int QueueEmpty(LinkQueue Q)//判断队列是否为空,为空则返回1,否则返回0int EnQueue(LinkQueue *Q,QElemType e) //向队列中插入元素int DeQueue(LinkQueue *Q,QElemType *e) //若队列不为空,则删除对头元素,并返回1;否则返回 0 void BFSTraverse(AMLGraph G ,int(*Visit)(VertexType)) //广度优先非递归遍历图G void MarkUnVisited(AMLGraph G) //把边的访问标记设置为0,即未被访问 void Display(AMLGraph G) //显示构造的无向图(包括定点数、顶点、边数、边)(三)程序总体框架(四)详细代码#include <iostream> using namespace std;//--------------------------------------------------------无向图的邻接多重表存储结构的定义 const int NUM=20;const int Data_Num=2;//每个顶点所表示的数据 开始创建无向图打印无向图深度优先搜索创建无向图结束typedef char VertexType[Data_Num];typedef struct EBox{int mark;//访问标记,1代表已访问,0代表未访问int ivex,jvex;//该边依附的两个顶点的位置struct EBox *ilink,*jlink;//分别指向依附这两个顶点的下一条边}EBox;typedef struct VexBox{VertexType data;EBox *firstedge;//指向第一条依附该顶点的边}VexBox;typedef struct{VexBox adjmulist[NUM];int vexnum,edgenum;//无向图的当前顶点数和边数}AMLGraph;//---------------------------------------------------队列的定义typedef int QElemType;typedef struct QNode{QElemType data;struct QNode *next;}QNode,*QueuePtr;typedef struct{QueuePtr front,rear;}LinkQueue;//寻找输入的数据在图中的位置,若不存在则返回-1int LocateVex(AMLGraph G,VertexType u){int i;for(i=0;i<G.vexnum;i++)if(strcmp(u,G.adjmulist[i].data)==0)return i;return -1;}//采用邻接多重表存储表示,构造无向图Gint CreateGraph(AMLGraph &G){cout<<"请输入图的顶点数、边数:";cin>>G.vexnum;//输入图当前的顶点数cin>>G.edgenum;//输入图当前的边数cout<<"请输入每个顶点所对应的值:"<<endl;for(int i=0;i<G.vexnum;i++){cin>>G.adjmulist[i].data;//输入顶点值G.adjmulist[i].firstedge=NULL;//初始化指针}VertexType v1,v2;EBox *p;int j;//每条弧所关联的两个结点for(int k=0;k<G.edgenum;k++){cout<<"请输入第"<<k<<"边的始点和终点:";cin>>v1;cin>>v2;i=LocateVex(G,v1);j=LocateVex(G,v2);//确定v1和v2在图G中的位置p=(EBox *)malloc(sizeof(EBox));//对弧结点进行赋值(*p).mark=0;(*p).ivex=i;(*p).jvex=j;(*p).ilink=G.adjmulist[i].firstedge;(*p).jlink=G.adjmulist[j].firstedge;G.adjmulist[i].firstedge=G.adjmulist[j].firstedge=p;}return 1;}//返回V的值VertexType* GetVex(AMLGraph G,int v){if(v>G.vexnum||v<0)exit(0);return &G.adjmulist[v].data;}//返回V的第一个邻接点的序号,若没有则返回-1int FirstAdjVex(AMLGraph G,VertexType v){int i;i=LocateVex(G,v);if(i<0)return -1;if(G.adjmulist[i].firstedge)//V有邻接结点if(G.adjmulist[i].firstedge->ivex==i)return G.adjmulist[i].firstedge->jvex;elsereturn G.adjmulist[i].firstedge->ivex;elsereturn -1;}//返回V的(相对于W)的下一个邻接结点的序号,若W是V的最后一个邻接结点,则返回-1 int NextAdjVex(AMLGraph G,VertexType v,VertexType w){int i,j;EBox *p;i=LocateVex(G,v);j=LocateVex(G,w);if(i<0||j<0)return -1;p=G.adjmulist[i].firstedge;while(p)if(p->ivex==i&&p->jvex!=j)p=p->ilink;else if(p->jvex==i&&p->ivex!=j)p=p->jlink;elsebreak;if(p&&p->ivex==i&&p->jvex==j){p=p->ilink;if(p&&p->ivex==i)return p->jvex;else if(p&&p->jvex==i)return p->jvex;}if(p&&p->ivex==j&&p->jvex==i){p=p->jlink;if(p&&p->ivex==i)return p->jvex;else if(p&&p->jvex==i)return p->jvex;}return -1;}//------------------------------------队列的操作int visite[NUM];//访问标志数组int (*VisitFunc)(VertexType v);void DFS(AMLGraph G,int v){int j;EBox *p;VisitFunc(G.adjmulist[v].data);visite[v]=1;//该顶点已经被访问p=G.adjmulist[v].firstedge;while(p){j=p->ivex==v?p->jvex:p->ivex;if(!visite[j])DFS(G,j);p=p->ivex==v?p->ilink:p->jlink;}}//深度优先遍历图void DFSTraverse(AMLGraph G,int(*Visit)(VertexType)) {int v,start;VisitFunc=Visit;for(v=0;v<G.vexnum;v++)visite[v]=0;cout<<"请输入你要开始进行查找的位置:";cin>>start;cout<<"按广深度优先搜索的结果是:"<<endl;for(v=start;v<G.vexnum;v++){if(v>=G.vexnum){for(v=0;v<G.vexnum;v++){if(!visite[v])DFS(G,v);}//内层for}//ifelse{if(!visite[v])DFS(G,v);}//else}//外层forcout<<"\b\b\b ";cout<<endl;}//队列的初始化int InitQueue(LinkQueue *Q){(*Q).front=(*Q).rear=(QueuePtr)malloc(sizeof(QNode));if(!(*Q).front)exit(0);(*Q).front->next=NULL;return 1;}//判断队列是否为空,为空则返回1,否则返回0int QueueEmpty(LinkQueue Q){if(Q.front==Q.rear)return 1;elsereturn 0;}//向队列中插入元素int EnQueue(LinkQueue *Q,QElemType e){QueuePtr p=(QueuePtr)malloc(sizeof(QNode));if(!p)exit(0);p->data=e;p->next=NULL;(*Q).rear->next=p;(*Q).rear=p;return 1;}//若队列不为空,则删除对头元素,并返回1;否则返回0 int DeQueue(LinkQueue *Q,QElemType *e){QueuePtr p;if((*Q).front==(*Q).rear)return 0;p=(*Q).front->next;*e=p->data;(*Q).front->next=p->next;if((*Q).rear==p)(*Q).rear=(*Q).front;free(p);return 1;}//广度优先非递归遍历图Gvoid BFSTraverse(AMLGraph G,int(*Visit)(VertexType)){int u,v,w,start=0;VertexType w1,u1;LinkQueue Q;for(v=0;v<G.vexnum;v++)visite[v]=0;InitQueue(&Q);cout<<"请输入你要开始进行查找的位置:";cin>>start;cout<<"按广度优先搜索的结果是:"<<endl;for(v=start;v<G.vexnum;v++){if(!visite[v]){visite[v]=1;Visit(G.adjmulist[v].data);EnQueue(&Q,v);//v入队列while(!QueueEmpty(Q)){DeQueue(&Q,&u);strcpy(u1,*GetVex(G,u));for(w=FirstAdjVex(G,u1);w>=0;w=NextAdjVex(G,u1,strcpy(w1,*GetVex(G,w))))if(!visite[w]){visite[w]=1;Visit(G.adjmulist[w].data);EnQueue(&Q,w);}}}}//forInitQueue(&Q);for(v=0;v<start;v++){if(!visite[v]){visite[v]=1;Visit(G.adjmulist[v].data);EnQueue(&Q,v);//v入队列while(!QueueEmpty(Q)){DeQueue(&Q,&u);strcpy(u1,*GetVex(G,u));for(w=FirstAdjVex(G,u1);w>=0;w=NextAdjVex(G,u1,strcpy(w1,*GetVex(G,w))))if(!visite[w]){visite[w]=1;Visit(G.adjmulist[w].data);EnQueue(&Q,w);}}}}//forcout<<"\b\b\b ";cout<<endl;}//把边的访问标记设置为0,即未被访问void MarkUnVisited(AMLGraph G){int i;EBox *p;for(i=0;i<G.vexnum;i++){p=G.adjmulist[i].firstedge;while(p){p->mark=0;if(p->ivex==i)p=p->ilink;elsep=p->jlink;}}}//显示构造的无向图(包括定点数、顶点、边数、边)void Display(AMLGraph G){int i;EBox *p;MarkUnVisited(G);cout<<G.vexnum<<"个顶点:";for(i=0;i<G.vexnum;i++)cout<<G.adjmulist[i].data<<" ";cout<<"; "<<G.edgenum<<"条边:"<<endl;for(i=0;i<G.vexnum;i++){p=G.adjmulist[i].firstedge;while(p)if(p->ivex==i){if(!p->mark){cout<<G.adjmulist[i].data<<"-->"<<G.adjmulist[p->jvex].data<<" ";p->mark=1;//已经被访问过了}p=p->ilink;}else{if(!p->mark){cout<<G.adjmulist[p->ivex].data<<"-->"<<G.adjmulist[i].data<<" ";p->mark=1;//已经被访问过了}p=p->jlink;}cout<<endl;}}int Visit(VertexType v){cout<<v<<"-->";return 1;}int main(){int flag=1,control,YES=0;AMLGraph g;while(flag){cout<<"\t\t-----------------------------------------------------"<<endl;cout<<"\t\t-------------请输入你要进行的操作:------------------"<<endl;cout<<"\t\t-----------1.创建无向图||2.打印无向图||----------"<<endl;cout<<"\t\t-----------3.深度优先搜索||4.广度优先搜索||----------"<<endl;cout<<"\t\t-----------0.退出系统--------------------------------"<<endl;cout<<"\t\t-----------------------------------------------------"<<endl;cin>>control;switch(control){case 1:YES=CreateGraph(g);break;case 2:if(YES)Display(g);else{cout<<"请先创建无向图,再选择此项"<<endl;}break;case 3:if(YES){DFSTraverse(g,Visit);}else{cout<<"请先创建无向图,再选择此项"<<endl;}break;case 4:if(YES){BFSTraverse(g,Visit);}else{cout<<"请先创建无向图,再选择此项"<<endl;}break;case 0:flag=0;break;}//switch}//whilereturn 0;}四、程序清单代码运行结果截图:主页面:1.创建无向图:输入6个顶点、9条边,如图:2.打印无向图:3.深度优先搜索4.广度搜索五、总结参考资料[1] 殷人昆 .《数据结构(用面向对象方法与c++语言描述)》清华大学出版社[2] 严蔚敏、吴伟民.《数据结构(C语言版)》清华大学出版社。
图的遍历和生成树求解实现(邻接矩阵、邻接表―图的深度广度遍历
图的遍历和生成树求解实现(邻接矩阵、邻接表―图的深度广度遍历算法的实现和最小生成树PRIM和KRUSCAL算法的实现)图的遍历和生成树求解实现(邻接矩阵、邻接表―图的深度广度遍历算法的实现和最小生成树PRIM和KRUSCAL算法的实现)#inc lude <iostream>#inc lude <malloc.h>using namespace std;#define int_max 10000#define inf 9999#define max 20//…………………………………………邻接矩阵定义……………………typedef struct ArcCell{int adj;char *info;}ArcCell,AdjMatrix[20][20];typedef struct{char vexs[20];AdjMatr ix arcs;int vexnum,arcnum;}MGraph_L;//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^int localvex(MGraph_L G,char v)//返回V的位置{int i=0;w hile(G.vexs[i]!=v){++i;}return i;}int creatMGr aph_L(MGraph_L &G)//创建图用邻接矩阵表示{char v1,v2;int i,j,w;cout<<"…………创建无向图…………"<<endl<<"请输入图G顶点和弧的个数:(4 6)不包括“()”"<<endl; cin>>G.vexnum>>G.arcnum;for(i=0;i!=G.vexnum;++i){cout<<"输入顶点"<<i<<endl;cin>>G.vexs[i];}for(i=0;i!=G.vexnum;++i)for(j=0;j!=G.vexnum;++j){G.arcs[i][j].adj=int_max;G.arcs[i][j].info=NULL;}for(int k=0;k!=G.arcnum;++k){cout<<"输入一条边依附的顶点和权:(a b 3)不包括“()”"<<endl;cin>>v1>>v2>>w;//输入一条边依附的两点及权值i=localvex(G,v1);//确定顶点V1和V2在图中的位置j=localvex(G,v2);G.arcs[i][j].adj=w;G.arcs[j][i].adj=w;}cout<<"图G邻接矩阵创建成功!"<<endl;return G.vexnum;}void ljjzprint(MGraph_L G){int i,j;for(i=0;i!=G.vexnum;++i){for(j=0;j!=G.vexnum;++j)cout<<G.arcs[i][j].adj<<" ";cout<<endl;}}int vis ited[max];//访问标记int w e;typedef struct arcnode//弧结点{int adjvex;//该弧指向的顶点的位置struct arcnode *nextarc;//弧尾相同的下一条弧char *info;//该弧信息}arcnode;typedef struct vnode//邻接链表顶点头接点{char data;//结点信息arcnode *firstarc;//指向第一条依附该结点的弧的指针}vnode,adjlist;typedef struct//图的定义{adjlist vertices[max];int vexnum,arcnum;int kind;}algraph;//…………………………………………队列定义……………………typedef struct qnode{int data;struct qnode *next;}qnode,*queueptr;typedef struct{queueptr front;queueptr rear;}linkqueue;//………………………………………………………………………typedef struct acr{int pre;//弧的一结点int bak;//弧另一结点int w eight;//弧的权}edg;int creatadj(algraph &gra,MGr aph_L G)//用邻接表存储图{int i=0,j=0;arcnode *arc,*tem,*p;for(i=0;i!=G.vexnum;++i){gra.vertices[i].data=G.vexs[i];gra.vertices[i].firstarc=NULL;}for(i=0;i!=G.vexnum;++i){for(j=0;j!=G.vexnum;++j){if(gra.vertices[i].firstarc==NULL){if(G.arcs[i][j].adj!=int_max&&j!=G.vexnum){arc=(arcnode *)malloc(sizeof(arcnode));arc->adjvex=j;gra.vertices[i].firstarc=arc;arc->nextarc=NULL;p=arc;++j;w hile(G.arcs[i][j].adj!=int_max&&j!=G.vexnum) {tem=(arcnode *)malloc(sizeof(arcnode));tem->adjvex=j;gra.vertices[i].firstarc=tem;tem->nextarc=arc;arc=tem;++j;}--j;}}else{if(G.arcs[i][j].adj!=int_max&&j!=G.vexnum){arc=(arcnode *)malloc(sizeof(arcnode));arc->adjvex=j;p->nextarc=arc;arc->nextarc=NULL;p=arc;}}}}gra.vexnum=G.vexnum;gra.arcnum=G.arcnum;/*for(i=0;i!=gra.vexnum;++i){arcnode *p;cout<<i<<" ";p=gra.vertices[i].firstarc;w hile(p!=NULL){cout<<p->adjvex;p=p->nextarc;}cout<<endl;}*/cout<<"图G邻接表创建成功!"<<endl;return 1;}void adjpr int(algraph gra){int i;for(i=0;i!=gra.vexnum;++i){arcnode *p;cout<<i<<" ";p=gra.vertices[i].firstarc;w hile(p!=NULL){cout<<p->adjvex;p=p->nextarc;}cout<<endl;}}int firstadjvex(algraph gra,vnode v)//返回依附顶点V的第一个点 //即以V为尾的第一个结点{if(v.firstarc!=NULL)return v.firstarc->adjvex;int nextadjvex(algraph gra,vnode v,int w)//返回依附顶点V的相对于W的下一个顶点{arcnode *p;p=v.firstarc;w hile(p!=NULL&&p->adjvex!=w){p=p->nextarc;}if(p->adjvex==w&&p->nextarc!=NULL){p=p->nextarc;return p->adjvex;}if(p->adjvex==w&&p->nextarc==NULL)return -10;}int initqueue(linkqueue &q)//初始化队列{q.rear=(queueptr)malloc(sizeof(qnode));q.front=q.rear;if(!q.front)return 0;q.front->next=NULL;return 1;}int enqueue(linkqueue &q,int e)//入队{queueptr p;p=(queueptr)malloc(sizeof(qnode));if(!p)return 0;p->data=e;p->next=NULL;q.rear->next=p;q.rear=p;return 1;}int dequeue(linkqueue &q,int &e)//出队{queueptr p;if(q.front==q.r ear)return 0;p=q.front->next;e=p->data;q.front->next=p->next;if(q.rear==p)q.rear=q.front;free(p);return 1;}int queueempty(linkqueue q)//判断队为空{if(q.front==q.r ear)return 1;return 0;}void bfstra(algraph gra)//广度优先遍历{int i,e;linkqueue q;for(i=0;i!=gra.vexnum;++i)visited[i]=0;initqueue(q);for(i=0;i!=gra.vexnum;++i)if(!visited[i]){ visited[i]=1;cout<<gr a.vertices[i].data;enqueue(q,i);w hile(!queueempty(q)){dequeue(q,e);// cout<<" "<<e<<" ";for(w e=firstadjvex(gra,gra.vertices[e]);w e>=0;w e=nextadjvex(gra,gra.vertices[e],w e)) {if(!v isited[w e]){visited[w e]=1;cout<<gra.vertices[w e].data;enqueue(q,w e);}}}}}int dfs(algraph gra,int i);//声明DFSint dfstra(algraph gra){int i,j;for(i=0;i!=gra.vexnum;++i){visited[i]=0;}for(j=0;j!=gra.vexnum;++j){if(visited[j]==0)dfs(gra,j);}return 0;}int dfs(algraph gra,int i){visited[i]=1;int w e1;// cout<<i<<visited[i]<<endl;cout<<gra.vertices[i].data;// cout<<endl;for(w e=firstadjvex(gra,gra.vertices[i]);w e>=0;w e=nextadjvex(gra,gra.vertices[i],w e)) {// cout<<w e<<visited[w e]<<endl;w e1=w e;// cout<<nextadjvex(gra,gra.vertices[i],w e)<<endl;if(visited[w e]==0)// cout<<dfs(gra,w e);//<<endl;// cout<<i<<w e1<<endl;w e=w e1;// cout<<nextadjvex(gra,gra.vertices[i],w e)<<endl;}return 12;}int bfstra_fen(algr aph gra)//求连通分量{int i,j;for(i=0;i!=gra.vexnum;++i){visited[i]=0;}for(j=0;j!=gra.vexnum;++j){if(visited[j]==0){dfs(gra,j);cout<<endl;}}return 0;}typedef struct{int adjvex;int low cost;}closedge;/*int minimum(c losedge *p);int minispantree(MGraph_L G,char u){int k,j,i;closedge closedge_a[20];k=localvex(G,u);// cout<<k<<endl;for(j=0;j!=G.vexnum;++j){if(j!=k){closedge_a[j].adjvex=u;closedge_a[j].low cost=G.arcs[k][j].adj;}for(i=1;i!=G.vexnum;++i){k=minimum(closedge_a);cout<<k;cout<<closedge_a[k].adjvex<<" "<<G.vexs[k]<<endl; closedge_a[k].low cost=0;for(j=0;j!=G.vexnum;++j)if(G.arcs[k][j].adj<closedge_a[j].low cost){closedge_a[j].adjvex=G.vexs[k];closedge_a[j].low cost=G.arcs[k][j].adj;}}}return 0;}int minimum(closedge *p){int s=10000;for(;p!=NULL;++p){if(s>p->lowcost)s=p->low cost;}return s;}*/int pr im(int g[][max],int n) //最小生成树PRIM算法{int low cost[max],prevex[max]; //LOWCOST[]存储当前集合U分别到剩余结点的最短路径 //prevex[]存储最短路径在U中的结点int i,j,k,min;for(i=2;i<=n;i++) //n个顶点,n-1条边{low cost[i]=g[1][i]; //初始化prevex[i]=1; //顶点未加入到最小生成树中}low cost[1]=0; //标志顶点1加入U集合for(i=2;i<=n;i++) //形成n-1条边的生成树{min=inf;k=0;for(j=2;j<=n;j++) //寻找满足边的一个顶点在U,另一个顶点在V的最小边if((lowcost[j]<min)&&(low cost[j]!=0)){min=low cost[j];k=j;}printf("(%d,%d)%d\t",prevex[k]-1,k-1,min);low cost[k]=0; //顶点k加入Ufor(j=2;j<=n;j++) //修改由顶点k到其他顶点边的权值if(g[k][j]<low cost[j]){low cost[j]=g[k][j];prevex[j]=k;}printf("\n");}return 0;}int acrvisited[100];//kruscal弧标记数组int find(int acrvisited[],int f){w hile(acrvisited[f]>0)f=acrvisited[f];return f;}void kruscal_arc(MGraph_L G,algraph gra) {edg edgs[20];int i,j,k=0;for(i=0;i!=G.vexnum;++i)for(j=i;j!=G.vexnum;++j){if(G.arcs[i][j].adj!=10000){edgs[k].pre=i;edgs[k].bak=j;edgs[k].w eight=G.arcs[i][j].adj;++k;}}int x,y,m,n;int buf,edf;for(i=0;i!=gra.arcnum;++i)acrvisited[i]=0;for(j=0;j!=G.arcnum;++j){m=10000;for(i=0;i!=G.arcnum;++i){if(edgs[i].w eight<m){m=edgs[i].w eight;x=edgs[i].pre;y=edgs[i].bak;n=i;}}// cout<<x<<y<<m;// cout<<endl;buf=find(acrvisited,x);edf=find(acrvisited,y);// cout<<buf<<" "<<edf<<endl;edgs[n].w eight=10000;if(buf!=edf){acrvisited[buf]=edf;cout<<"("<<x<<","<<y<<")"<<m;cout<<endl;}}}void main(){algraph gr a;MGraph_L G;int i,d,g[20][20];char a='a';d=creatMGr aph_L(G);creatadj(gra,G);vnode v;cout<<endl<<"……####注意:若该图为非强连通图(含有多个连通分量)时"<<endl <<" 最小生成树不存在,则显示为非法值。
图的广度遍历(算法与数据结构课程设计)
1 问题描述图是一种较线性表和树更为复杂的数据结构。
在图形结构中,节点间的关系可以是任意的,图中任意两个数据元素之间都可以相关。
由此,图的应用极为广泛。
现在邻接矩阵和邻接表的存储结构下,完成图的广度遍历。
对任意给定的图(顶点数和边数自定),建立它的邻接表并输出,然后利用队列的五种基本运算(置空队列、进队、出队、取队头元素、判队空)实现图的广度优先搜索遍历。
画出搜索顺序示意图。
2 分析与解决问题2.1 基本要求(1) 选择合适的存储结构完成图的建立;(2) 建立图的邻接矩阵,能按矩阵方式输出图,并在此基础上,完成图的广度遍历,输出遍历序列;(3) 建立图的邻接表,并在此基础上,完成图的广度遍历,输出遍历序列;2.2 测试数据图1-1 测试图2.3 算法思想(1) 邻接矩阵顶点向量的存储。
用两个数组分别存储数据(定点)的信息和数据元素之间的关系(边或弧)的信息。
(2) 邻接表邻接表是图的一种链式存储结构。
在邻接表中,对图中每个定点建立一个单链表,第i个单链表中的节点表示依附于定点vi的边。
每个节点由3个域组成,其中邻接点域(adjvex)指示与定点vi邻接的点在图中的位置,链域(nextarc)指示下一条边或弧的节点;数据域(info)存储和边或弧相关的信息,如权值等。
每个链表上附设一个头节点。
在表头节点中,除了设有链域(firstarc)指向链表中第一个节点之外,还设有存储定点vi的名或其他有关信息的数据域(data)。
(3)图的广度遍历广度优先遍历类似于树的按层次遍历过程。
假设从图中某顶点v出发,在访问了v之后依次访问v的各个未曾访问过的邻接点,然后分别从这些邻接点出发依次访问它们的邻接点,并使“先被访问的顶点的邻接点”先与“后被访问的顶点的邻接点”被访问,直至图中所有已被访问的顶点的邻接点都被访问到。
若此时图中尚有顶点未被访问,则另选图中一个曾被访问的顶点作起始点,重复上述过程,直至图中所有顶点都被访问到为止。
数据结构课程设计题目整理
数据结构课程设计题目1.飞机订票系统(限1 人完成)(顺序或链式存储)任务:通过此系统可以实现如下功能:录入:可以录入航班情况(数据可以存储在一个数据文件中,数据结构、具体数据自定)查询:可以查询某个航线的情况(如,输入航班号,查询起降时间,起飞抵达城市,航班票价,票价折扣,确定航班是否满仓);可以输入起飞抵达城市,查询飞机航班情况;订票:(订票情况可以存在一个数据文件中,结构自己设定)可以订票,如果该航班已经无票,可以提供相关可选择航班;退票:可退票,退票后修改相关数据文件;客户资料有姓名,证件号,订票数量及航班情况,订单要有编号。
修改航班信息:当航班信息改变可以修改航班数据文件要求:根据以上功能说明,设计航班信息,订票信息,客户信息的存储结构,设计程序完成功能;2.宿舍管理查询软件(限1 人完成)任务:为宿舍管理人员编写一个宿舍管理查询软件, 程序设计要求:采用交互工作方式建立数据文件,包括学生信息、宿舍信息、住宿信息,学生信息按关键字(姓名、学号)进行排序(排序方法自选,不能相同);查询: (用二分查找实现以下操作)按姓名查询按学号查询(用顺序查找实现以下操作)按房号查询3.校园导航问题(限1 人完成)设计要求:设计你的学校的平面图,至少包括10个以上的场所,每两个场所间可以有不同的路,且路长也可能不同,找出从任意场所到达另一场所的最佳路径(最短路径)。
要求:能增加场所4.图书借阅管理系统(限1 人完成)(顺序或链式存储)主要分为两大功能:1)图书管理(增加图书、查询图书、删除图书、图书借阅、还书);2)会员管理(增加会员、查询会员、删除会员、借书信息);5.学生成绩管理(限1 人完成)(顺序或链式存储)包括:课程信息,学生信息等;能增加课程或学生。
实现功能:输入、输出、插入、删除、查找、显示、保存、排序、退出。
6.活期储蓄帐目管理(限1 人完成)活期储蓄处理中,储户开户、销户、存入、支出活动频繁,系统设计要求:1)能比较迅速地找到储户的帐户,以实现存款、取款记账;2)能比较简单,迅速地实现插入和删除,以实现开户和销户的需要。
树的遍历与生成树PPT课件
7.3 树的遍历 Tree Traversal
例1 前序遍历是以什么顺序访问 图中有序根树里的顶点的?
a b e j k n o p f c d g l m h i 第3页/共48页
7.3 树的遍历 Tree Traversal
[定义2] 设T是带根r的有序根树。若T只包含r,则r是T的中序 遍历。否则T1,T2,…,Tn是T里在r处从左到右的子树。中 序遍历首先以中序来遍历T1 ,然后访问r,接着以中序遍历 T2 ,以中序遍历T3 ,依此类推,直到以中序遍历了Tn为止。
T=(V, E'), E'E
例1 找出下面简单图的生成树。
第25页/共48页
7.4 生成树和最小生成树
Spanning Trees and minimum Spanning Trees
[定理1] 无向简单图G=(V, E)存在生成树的充要条件是 G是连通的。
证明:必要性:T是生成子图,包含G的所有顶点,T是树,T 连通,则G连通。
第9页/共48页
7.3 树的遍历 Tree Traversal
第10页/共48页
7.3 树的遍历 Tree Traversal
• 以前序、中序、后序来列出有序根树的顶点的简易方法:
• 首先从根开始围绕有序根树画一条曲线,沿着边移动; • 前序:当曲线第一次经过一个顶点
时,就列出这个顶点
• 中序:当曲线第一次经过一个树叶 时,就列出这个树叶,当曲线第二 次经过一个内点时就列出这个内点
7.3 树的遍历 Tree Traversal
• 有序根树常常用来保存信息,因此掌握访问有序根树的 每个顶点以存取数据信息的算法非常必要
• 系统地访问有序根树每个顶点的过程都称为遍历算法 • 前序遍历 Preorder traversal • 中序遍历 Inorder traversal • 后序遍历 Postorder traversal
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
图的遍历和生成树求解实现的课程结构设计一.问题描述:1.图的遍历和生成树求解实现图是一种较线性表和树更为复杂的数据结构。
在线性表中,数据元素之间仅有线性关系,每个数据元素只有一个直接前驱和一个直接后继;在树形结构中,数据元素之间有着明显的层次关系,并且每一层上的数据元素可能和下一层中多个元素(及其孩子结点)相关但只能和上一层中一个元素(即双亲结点)相关;而在图形结构中,节点之间的关系可以是任意的,图中任意两个数据元素之间都可能相关。
生成树求解主要利用普利姆和克雷斯特算法求解最小生成树,只有强连通图才有生成树。
2.基本功能1) 先任意创建一个图;2) 图的DFS,BFS的递归和非递归算法的实现3) 最小生成树(两个算法)的实现,求连通分量的实现4) 要求用邻接矩阵、邻接表等多种结构存储实现3.输入输出输入数据类型为整型和字符型,输出为整型和字符二、概要设计1.设计思路:a.图的邻接矩阵存储:根据所建无向图的结点数n,建立n*n的矩阵,其中元素全是无穷大(int_max),再将边的信息存到数组中。
其中无权图的边用1表示,无边用0表示;有全图的边为权值表示,无边用∞表示。
b.图的邻接表存储:将信息通过邻接矩阵转换到邻接表中,即将邻接矩阵的每一行都转成链表的形式将有边的结点进行存储。
c.图的广度优先遍历:假设从图中的某个顶点v出发,在访问了v之后依次访问v的各个未曾访问过的邻接点,然后再访问此邻接点的未被访问的邻接点,并使“先被访问的顶点的邻接点”先于“后被访问的顶点的邻接点”被访问,直至图中所有已被访问的顶点的邻接点都被访问到。
若此时图中还有未被访问的,则另选未被访问的重复以上步骤,是一个非递归过程。
d.图的深度优先遍历:假设从图中某顶点v出发,依依次访问v的邻接顶点,然后再继续访问这个邻接点的系一个邻接点,如此重复,直至所有的点都被访问,这是个递归的过程。
e.图的连通分量:这是对一个非强连通图的遍历,从多个结点出发进行搜索,而每一次从一个新的起始点出发进行搜索过程中得到的顶点访问序列恰为其连通分量的顶点集。
本程序利用的图的深度优先遍历算法。
2.数据结构设计:ADT Queue{数据对象:D={ai | ai∈ElemSet,i=1,2,3……,n,n≥0}数据关系:R1={<ai-1,ai>| ai-1,ai∈D,i=1,2,3,……,n}基本操作:InitQueue(&Q)操作结果:构造一个空队列Q。
QueueEmpty(Q)初始条件:Q为非空队列。
操作结果:若Q为空队列,则返回真,否则为假。
EnQueue(&Q,e)初始条件:Q为非空队列。
操作结果:插入元素e为Q的新的队尾元素。
DeQueue(&Q,e)初始条件:Q为非空队列。
操作结果:删除Q的队头元素,并用e返回其值。
}ADT QueueADT Graph{数据对象V:V是具有相同特性的数据元素的集合,称为顶点集。
数据关系R:R={VR}VR={<v,w>|v,w∈V且P(v,w),<v,w>表示从v到w的弧,谓词P(v,w)定义了弧<v,w>的意义或信息}基本操作P:CreatGraph(&G,V,VR);初始条件:V是图的顶点集,VR是图中弧的集合。
操作结果:按V和VR的定义构造图G。
BFSTraverse(G,visit());初始条件:图G存在,Visit是定点的应用函数。
操作结果:对图进行广度优先遍历。
在遍历过程中对每个顶点调用函数Visit一次且仅一次。
一旦visit()失败,则操作失败。
DFSTraverse(G,visit());初始条件:图G存在,Visit是定点的应用函数。
操作结果:对图进行广度优先遍历。
在遍历过程中对每个顶点调用函数Visit一次且仅一次。
一旦visit()失败,则操作失败。
DFStra_fen(G)初始条件:图G存在,存在图的深度优先遍历算法。
操作结果:从多个顶点对图进行深度优先遍历,得到连通分量。
}ADT Graph;3.软件结构设计:三、详细设计1.定义程序中所有用到的数据及其数据结构,及其基本操作的实现;邻接矩阵定义:typedef struct ArcCell{VRType adj;//VRType是顶点关系类型。
对无权图,用1或0表示相邻否;对带权图,则为权值类型InfoType *info;//该弧相关信息的指针}ArcCell,AdjMatrix[max][max];typedef struct{VertexType vexs[max];//顶点向量AdjMatrix arcs;//邻接矩阵int vexnum,arcnum;//图的当前顶点数和弧数}MGraph_L;邻接表的定义:typedef struct ArcNode//弧结点{int adjvex;//该弧指向的顶点的位置struct ArcNode *nextarc;//指向下一条弧的指针InfoType *info;//该弧相关信息的指针}ArcNode;typedef struct VNode//邻接链表顶点头接点{VertexType data;//顶点信息ArcNode *firstarc;//指向第一条依附该顶点的弧的指针}VNode,AdjList;typedef struct//图的定义{AdjList vertices[max];int vexnum,arcnum;//图的当前顶点数和弧数}ALGraph;队列定义:typedef struct QNode{QElemType data;struct QNode *next;}QNode,*QueuePtr;typedef struct{QueuePtr front;//队头指针QueuePtr rear;//队尾指针}LinkQueue;2.主函数和其他函数的伪码算法;主函数:int main(){int s;char y='y';cout<<"||¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤菜单¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤||"<<endl;cout<<"||-------------------------【0、创建一个无向图------------------------------||"<<endl;cout<<"||-------------------------【1、显示该图的邻接矩阵--------------------------||"<<endl;cout<<"||-------------------------【2、显示该图的邻接表----------------------------||"<<endl;cout<<"||-------------------------【3、广度优先遍历--------------------------------||"<<endl;cout<<"||-------------------------【4、深度优先遍历--------------------------------||"<<endl;cout<<"||-------------------------【5、最小生成树MiniSpanTree_PRIM 算法-------------||"<<endl;cout<<"||-------------------------【6、最小生成树MiniSpanTree_KRUSCAL算法----------||"<<endl;cout<<"||-------------------------【7、连通分量------------------------------------||"<<endl;cout<<"||¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤||"<<endl;while(y=='y'){cout<<"请选择菜单:"<<endl;cin>>s;if(s==0){++o;if(o==2){n=0;l=0;o=0;}}switch(s){case 0:cout<<"创建一个无向图:"<<endl;MGraph_L G;creatMGraph_L(G);ALGraph gra;creatadj(gra,G);break;case 1:cout<<"邻接矩阵显示如下:"<<endl;ljjzprint(G);break;case 2:cout<<"邻接表显示如下:"<<endl;adjprint(gra,G);break;case 3:cout<<"广度优先遍历:";BFSTraverse(gra);cout<<endl;break;case 4:cout<<"深度优先遍历:";DFStra(gra);cout<<endl;break;case 5:if(n==0){cout<<"无权图没有最小生成树";break;}else if(l>0){cout<<"若该图为非强连通图(含有多个连通分量)时,最小生成树不存在"<<endl;break;}else{int i,g[max][max];for(i=0;i!=G.vexnum;++i)for(int j=0;j!=G.vexnum;++j)g[i+1][j+1]=G.arcs[i][j].adj;cout<<"普利姆算法:"<<endl;MiniSpanTree_PRIM(g,G.vexnum);break;}case 6:if(n==0){cout<<"无权图没有最小生成树";break;}else if(l>0){cout<<"该图为非强连通图(含有多个连通分量),最小生成树不存在"<<endl;break;}else{cout<<"克鲁斯卡尔算法:"<<endl;MiniSpanTREE_KRUSCAL(G,gra);break;}case 7:cout<<"连通分量:"<<endl;DFSTraverse_fen(gra);break;}cout<<endl<<"是否继续?y/n:";cin>>y;if(y=='n')break;}return 0;}邻接矩阵存储:int creatMGraph_L(MGraph_L &G)//创建图用邻接矩阵表示{char v1,v2;int i,j,w;cout<<"请输入顶点和弧的个数"<<endl;cin>>G.vexnum>>G.arcnum;cout<<"输入各个顶点"<<endl;for(i=0;i<G.vexnum;++i){cin>>G.vexs[i];}for(i=0;i<G.vexnum;++i)for(j=0;j<G.vexnum;++j){G.arcs[i][j].adj=int_max;G.arcs[i][j].info=NULL;for(int k=0;k<G.arcnum;++k){cout<<"输入一条边依附的顶点和权"<<endl;cin>>v1>>v2>>w;//输入一条边依附的两点及权值i=localvex(G,v1);//确定顶点V1和V2在图中的位置j=localvex(G,v2);G.arcs[i][j].adj=w;G.arcs[j][i].adj=w;}for(i=0;i!=G.vexnum;++i)for(j=0;j!=G.vexnum;++j){if(G.arcs[i][j].adj!=1&&G.arcs[i][j].adj<int_max)n+=1;}if(n>=1)cout<<"这是一个有权图"<<endl;else cout<<"这是一个无权图"<<endl;cout<<"图G邻接矩阵创建成功!"<<endl;return G.vexnum;}邻接矩阵的输出:void ljjzprint(MGraph_L G) //邻接矩阵的输出{int i,j;if(n==0){for(i=0;i!=G.vexnum;++i){for(j=0;j!=G.vexnum;++j){if(G.arcs[i][j].adj==int_max){cout<<"0"<<" ";}else {cout<<G.arcs[i][j].adj<<" ";}}cout<<endl;}}{for(i=0;i!=G.vexnum;++i){for(j=0;j!=G.vexnum;++j){if(G.arcs[i][j].adj==int_max){cout<<"∞"<<" ";}else {cout<<G.arcs[i][j].adj<<" ";}}cout<<endl;}}}用邻接表存储图:int creatadj(ALGraph &gra,MGraph_L G)//用邻接表存储图{int i=0,j=0;ArcNode *arc;//,*tem,*p;for(i=0;i!=G.vexnum;++i){gra.vertices[i].data=G.vexs[i];gra.vertices[i].firstarc=NULL;}for(i=0;i!=G.vexnum;++i)for(j=0;j!=G.vexnum;++j){if(G.arcs[i][j].adj!=int_max){arc=(ArcNode *)malloc(sizeof(ArcNode));arc->adjvex=j;arc->nextarc=gra.vertices[i].firstarc;gra.vertices[i].firstarc=arc;}}gra.vexnum=G.vexnum;gra.arcnum=G.arcnum;cout<<"图G邻接表创建成功!"<<endl;return 1;}邻接表输出:void adjprint(ALGraph gra,MGraph_L G) //邻接表输出{int i;for(i=0;i!=gra.vexnum;++i){ArcNode *p;cout<<"["<<i<<","<<G.vexs[i]<<"]";p=gra.vertices[i].firstarc;while(p!=NULL){cout<<"->"<<"["<<p->adjvex<<"]";p=p->nextarc;}cout<<"->"<<"End";cout<<endl;}}初始化队列:Status InitQueue(LinkQueue &Q)//初始化队列{Q.front=Q.rear=(QueuePtr)malloc(sizeof(QNode));if(!Q.front)return 0;//存储分配失败Q.front->next=NULL;return 1;}入队:Status EnQueue(LinkQueue &Q,QElemType e)//入队,插入元素e为Q的新的队尾元素{QueuePtr p;p=(QueuePtr)malloc(sizeof(QNode));if(!p)return 0;//存储分配失败p->data=e;p->next=NULL;Q.rear->next=p;Q.rear=p;return 1;}出队:Status DeQueue(LinkQueue &Q,QElemType &e)//出队,若队列不空,则删除Q 的队头元素,用e返回,并返回真,否则假{QueuePtr p;if(Q.front==Q.rear)return 0;p=Q.front->next;e=p->data;Q.front->next=p->next;if(Q.rear==p)Q.rear=Q.front;free(p);return 1;}判断队为空:Status QueueEmpty(LinkQueue Q)//判断队为空{if(Q.front==Q.rear) return 1;return 0;}广度优先遍历:void BFSTraverse(ALGraph gra){int i,e;LinkQueue q;for(i=0;i!=gra.vexnum;++i)visited[i]=0;InitQueue(q);for(i=0;i!=gra.vexnum;++i)if(!visited[i]){visited[i]=1;cout<<gra.vertices[i].data;EnQueue(q,i);while(!QueueEmpty(q)){DeQueue(q,e);for(we=firstadjvex(gra,gra.vertices[e]);we>=0;we=nextadjvex(gra,g ra.vertices[e],we)){if(!visited[we]){visited[we]=1;cout<<gra.vertices[we].data;EnQueue(q,we);}}}}}深度优先遍历:int DFS(ALGraph gra,int i){visited[i]=1;int we1;cout<<gra.vertices[i].data;for(we=firstadjvex(gra,gra.vertices[i]);we>=0;we=nextadjvex(gra,g ra.vertices[i],we)){we1=we;if(visited[we]==0)DFS(gra,we);we=we1;}return 1;}int DFStra(ALGraph gra){int i,j;for(i=0;i!=gra.vexnum;++i){visited[i]=0;}for(j=0;j!=gra.vexnum;++j){if(visited[j]==0)DFS(gra,j);}return 0;}连通分量:int DFSTraverse_fen(ALGraph gra) {int i,j;for(i=0;i!=gra.vexnum;++i)visited[i]=0;for(j=0;j!=gra.vexnum;++j){if(visited[j]==0){DFS(gra,j);cout<<endl;l++;}}return 0;}3.主要函数的程序流程图,实现设计中主程序和其他子模块的算法,以流程图的形式表示。