数据结构课程设计之图的遍历和生成树求解

合集下载

数据结构中的树与图算法教程

数据结构中的树与图算法教程

数据结构中的树与图算法教程第一章树的基本概念与遍历算法树是一种非线性数据结构,它由若干个节点组成,这些节点以层级的方式连接,形成分支的结构。

树中的一个节点被称为根节点,它没有父节点;其他节点可以有一个或多个父节点,这些节点被称为子节点。

树具有分支,但没有循环。

1.1 具体树的概念在树的结构中,每个节点可以有零个或者多个子节点,但是只能有一个父节点。

树具有层级关系,通过连接节点的边表示。

1.2 树的分类常见的树包括二叉树、二叉搜索树、红黑树等。

其中,二叉树是一种特殊的树结构,它的每个节点最多可以有两个子节点。

1.3 树的遍历算法树的遍历算法主要有前序遍历、中序遍历和后序遍历。

前序遍历是以根节点、左子树、右子树的顺序进行遍历;中序遍历是以左子树、根节点、右子树的顺序进行遍历;后序遍历是以左子树、右子树、根节点的顺序进行遍历。

第二章树的存储结构与常见应用2.1 树的存储结构树的存储结构有两种常见的实现方式,分别是链表实现和数组实现。

链表实现利用指针进行节点的连接,数组实现则使用数组的索引来表示节点之间的关系。

2.2 平衡二叉树平衡二叉树是一种自平衡的二叉搜索树,它的左右子树的高度差不超过1。

平衡二叉树的插入和删除操作都可以通过旋转操作进行平衡。

2.3 哈夫曼树哈夫曼树是一种特殊的二叉树,用于编码和解码数据。

哈夫曼树中出现频率高的字符距离根节点较近,而出现频率低的字符距离根节点较远,以实现编码的高效率。

第三章图的基本概念与遍历算法3.1 图的基本概念图是由节点和边组成的非线性数据结构。

节点表示实体,边表示节点之间的关系。

图可以分为有向图和无向图两种类型,有向图的边是有方向的,无向图的边没有方向。

3.2 图的存储结构图的存储结构有邻接矩阵和邻接表两种常见的方式。

邻接矩阵是一个二维数组,用于表示节点之间的连接关系;邻接表是由链表或者数组实现的,用于表示每个节点相邻节点的信息。

3.3 图的遍历算法图的遍历算法主要有深度优先搜索(DFS)和广度优先搜索(BFS)。

《数据结构》课程教学大纲(三套)

《数据结构》课程教学大纲(三套)

数据结构课程教学大纲(三套)《数据结构》课程教学大纲(36/36 课时)一、课程的性质和任务数据结构是计算机及应用专业中一门重要的专业基础课程,在计算机软件的各个领域中均会使用到数据结构的有关知识。

当用计算机来解决实际问题时,就要涉及到数据的表示及数据的处理,而数据表示及数据处理正是数据结构课程的主要研究对象,通过这两方面内容的学习,为后续课程,特别是软件方面的课程打开厚实的基础。

因此,数据结构课程在计算机应用专业中具有举足轻重的作用。

本课程的任务是:在基础方面,要求学员掌握常用数据结构的基本概念及其不同的实现方法;在技能方面,通过系统学习能够在不同存储结构上实现不同的运算,并对算法设计的方式和技巧有所体会。

总言之,使应用者较全面的掌握各种常用的数据结构,提高运用数据结构解决实际问题的能力。

二、课程的基本要求本课程的教学基本要求如下:本课程要求理论必须与上机实践操作相结合,多做题和调试算法,实现算法。

实践项目只利用课堂时间是不够的,必须提前布置给学生。

通过本课程的学习与实践,学生应达到:1、掌握数据结构的基本概念和基本理论;2、熟练掌握顺序表、链表、队列、栈、树以及二叉树、图等基本数据结构的设计和分析;3、熟练地掌握常用算法(递归、遍历、查找、排序)的知识;4、能对所求解的问题进行分析,抽象出逻辑结构,选择合适的存储结构定义所需的运算,设计相应的算法;5、对算法进行分析和评价。

三、教学内容(一)理论教学(二)实践环节四、课时分配《数据结构》课程共4学分,课内72学时,其中理论课36学时,上机36学时。

五、大纲说明本课程必须理论与上机实践操作相结合,并要教、学、练相结合,讲清基本概念,指出知识要点、重点和难点,并通过实例分析解决算法难点;要求学生认真预习、认真听课、认真思索、认真做实验, 通过对算法的编程实现来提高学生 由于内容多、 难度大, 要特别注重精讲多练, 实践项目一定 要提前布置给学生, 调动学生的主观能动性,鼓励学生多提 问题、共同探讨和解决问题。

数据结构实验报告图的遍历讲解

数据结构实验报告图的遍历讲解

数据结构实验报告图的遍历讲解一、引言在数据结构实验中,图的遍历是一个重要的主题。

图是由顶点集合和边集合组成的一种数据结构,常用于描述网络、社交关系等复杂关系。

图的遍历是指按照一定的规则,挨次访问图中的所有顶点,以及与之相关联的边的过程。

本文将详细讲解图的遍历算法及其应用。

二、图的遍历算法1. 深度优先搜索(DFS)深度优先搜索是一种常用的图遍历算法,其基本思想是从一个顶点出发,沿着一条路径向来向下访问,直到无法继续为止,然后回溯到前一个顶点,再选择此外一条路径继续访问。

具体步骤如下:(1)选择一个起始顶点v,将其标记为已访问。

(2)从v出发,选择一个未被访问的邻接顶点w,将w标记为已访问,并将w入栈。

(3)如果不存在未被访问的邻接顶点,则出栈一个顶点,继续访问其它未被访问的邻接顶点。

(4)重复步骤(2)和(3),直到栈为空。

2. 广度优先搜索(BFS)广度优先搜索是另一种常用的图遍历算法,其基本思想是从一个顶点出发,挨次访问其所有邻接顶点,然后再挨次访问邻接顶点的邻接顶点,以此类推,直到访问完所有顶点。

具体步骤如下:(1)选择一个起始顶点v,将其标记为已访问,并将v入队。

(2)从队首取出一个顶点w,访问w的所有未被访问的邻接顶点,并将这些顶点标记为已访问,并将它们入队。

(3)重复步骤(2),直到队列为空。

三、图的遍历应用图的遍历算法在实际应用中有广泛的应用,下面介绍两个典型的应用场景。

1. 连通分量连通分量是指图中的一个子图,其中的任意两个顶点都是连通的,即存在一条路径可以从一个顶点到达另一个顶点。

图的遍历算法可以用来求解连通分量的个数及其具体的顶点集合。

具体步骤如下:(1)对图中的每一个顶点进行遍历,如果该顶点未被访问,则从该顶点开始进行深度优先搜索或者广度优先搜索,将访问到的顶点标记为已访问。

(2)重复步骤(1),直到所有顶点都被访问。

2. 最短路径最短路径是指图中两个顶点之间的最短路径,可以用图的遍历算法来求解。

数据结构第七章-图

数据结构第七章-图

*
V0
V7
V6
V5
V4
V3
V2
V1
若图的存储结构为邻接表,则 访问邻接点的顺序不唯一, 深度优先序列不是唯一的
V0
V1
V3
V2
V7
V6
V5
V4
V0,V1,V3,V4,V7,V2,V5,V6,
※求图G以V0为起点的的深度优先序列(设存储结构为邻接矩阵)
void DFSAL(ALGraph G, int i) {/*从第v个顶点出发,递归地深度优先遍历图G*/ /* v是顶点的序号,假设G是用邻接表存储*/ EdgeNode *p; int w; visited[i] =1; Visit(i); /*访问第v个顶点*/ for (p=G.vertices[i].firstarc;p;p=p->nextarc) {w=p->adjvex; /*w是v的邻接顶点的序号*/ if (!visited[w]) DFSAL(G, w); /*若w尚未访问, 递归调用DFS*/ } }/*DFSAL*/
在邻接表存储结构上的广度优先搜索
*
Q
V0
V1
V2
V3
V4
V7
V5
V6
V1
V2
V3
V0
V4
V7
V5
V6
V0
V7
V6
V5
V4
V3
V2
V1
7.3 图的遍历
7
0
1
2
V0
V2
V3
V1
data
firstarc
0
1
^
^
adjvex
next
3

数据结构入门-树的遍历以及二叉树的创建

数据结构入门-树的遍历以及二叉树的创建

数据结构⼊门-树的遍历以及⼆叉树的创建树定义:1. 有且只有⼀个称为根的节点2. 有若⼲个互不相交的⼦树,这些⼦树本⾝也是⼀个树通俗的讲:1. 树是有结点和边组成,2. 每个结点只有⼀个⽗结点,但可以有多个⼦节点3. 但有⼀个节点例外,该节点没有⽗结点,称为根节点⼀、专业术语结点、⽗结点、⼦结点、根结点深度:从根节点到最底层结点的层数称为深度,根节点第⼀层叶⼦结点:没有⼦结点的结点⾮终端节点:实际上是⾮叶⼦结点度:⼦结点的个数成为度⼆、树的分类⼀般树:任意⼀个结点的⼦结点的个数都不受限制⼆叉树:任意⼀个结点的⼦结点个数最多是两个,且⼦结点的位置不可更改⼆叉数分类:1. ⼀般⼆叉数2. 满⼆叉树:在不增加树层数的前提下,⽆法再多添加⼀个结点的⼆叉树3. 完全⼆叉树:如果只是删除了满⼆叉树最底层最右边的连续若⼲个结点,这样形成的⼆叉树就是完全⼆叉树森林:n个互不相交的树的集合三、树的存储⼆叉树存储连续存储(完全⼆叉树)优点:查找某个结点的⽗结点和⼦结点(也包括判断有没有⼦结点)速度很快缺点:耗⽤内存空间过⼤链式存储⼀般树存储1. 双亲表⽰法:求⽗结点⽅便2. 孩⼦表⽰法:求⼦结点⽅便3. 双亲孩⼦表⽰法:求⽗结点和⼦结点都很⽅便4. ⼆叉树表⽰法:把⼀个⼀般树转化成⼀个⼆叉树来存储,具体转换⽅法:设法保证任意⼀个结点的左指针域指向它的第⼀个孩⼦,右指针域指向它的兄弟,只要能满⾜此条件,就可以把⼀个⼀般树转化为⼆叉树⼀个普通树转换成的⼆叉树⼀定没有右⼦树森林的存储先把森林转化为⼆叉树,再存储⼆叉树四、树的遍历先序遍历:根左右先访问根结点,再先序访问左⼦树,再先序访问右⼦树中序遍历:左根右中序遍历左⼦树,再访问根结点,再中序遍历右⼦树后续遍历:左右根后续遍历左⼦树,后续遍历右⼦树,再访问根节点五、已知两种遍历求原始⼆叉树给定了⼆叉树的任何⼀种遍历序列,都⽆法唯⼀确定相应的⼆叉树,但是如果知道了⼆叉树的中序遍历序列和任意的另⼀种遍历序列,就可以唯⼀地确定⼆叉树已知先序和中序求后序先序:ABCDEFGH中序:BDCEAFHG求后序:这个⾃⼰画个图体会⼀下就可以了,⾮常简单,这⾥简单记录⼀下1. ⾸先根据先序确定根,上⾯的A就是根2. 中序确定左右,A左边就是左树(BDCE),A右边就是右树(FHG)3. 再根据先序,A左下⾯就是B,然后根据中序,B左边没有,右边是DCE4. 再根据先序,B右下是C,根据中序,c左下边是D,右下边是E,所以整个左树就确定了5. 右树,根据先序,A右下是F,然后根据中序,F的左下没有,右下是HG,6. 根据先序,F右下为G,然后根据中序,H在G的左边,所以G的左下边是H再来⼀个例⼦,和上⾯的思路是⼀样的,这⾥就不详细的写了先序:ABDGHCEFI中序:GDHBAECIF已知中序和后序求先序中序:BDCEAFHG后序:DECBHGFA这个和上⾯的思路是⼀样的,只不过是反过来找,后序找根,中序找左右树简单应⽤树是数据库中数据组织⼀种重要形式操作系统⼦⽗进程的关系本⾝就是⼀棵树⾯向对象语⾔中类的继承关系哈夫曼树六、⼆叉树的创建#include <stdio.h>#include <stdlib.h>typedef struct Node{char data;struct Node * lchild;struct Node * rchild;}BTNode;/*⼆叉树建⽴*/void BuildBT(BTNode ** tree){char ch;scanf("%c" , &ch); // 输⼊数据if(ch == '#') // 如果这个节点的数据是#说明这个结点为空*tree = NULL;else{*tree = (BTNode*)malloc(sizeof(BTNode));//申请⼀个结点的内存 (*tree)->data = ch; // 将数据写⼊到结点⾥⾯BuildBT(&(*tree)->lchild); // 递归建⽴左⼦树BuildBT(&(*tree)->rchild); // 递归建⽴右⼦树}}/*⼆叉树销毁*/void DestroyBT(BTNode *tree) // 传⼊根结点{if(tree != NULL){DestroyBT(tree->lchild);DestroyBT(tree->rchild);free(tree); // 释放内存空间}}/*⼆叉树的先序遍历*/void Preorder(BTNode * node){if(node == NULL)return;else{printf("%c ",node->data );Preorder(node->lchild);Preorder(node->rchild);}}/*⼆叉树的中序遍历*/void Inorder(BTNode * node){if(node == NULL)return;else{Inorder(node->lchild);printf("%c ",node->data );Inorder(node->rchild);}}/*⼆叉树的后序遍历*/void Postorder(BTNode * node){if(node == NULL)return;else{Postorder(node->lchild);Postorder(node->rchild);printf("%c ",node->data );}}/*⼆叉树的⾼度树的⾼度 = max(左⼦树⾼度,右⼦树⾼度) +1*/int getHeight(BTNode *node){int Height = 0;if (node == NULL)return 0;else{int L_height = getHeight(node->lchild);int R_height = getHeight(node->rchild);Height = L_height >= R_height ? L_height +1 : R_height +1; }return Height;}int main(int argc, char const *argv[]){BTNode * BTree; // 定义⼀个⼆叉树printf("请输⼊⼀颗⼆叉树先序序列以#表⽰空结点:");BuildBT(&BTree);printf("先序序列:");Preorder(BTree);printf("\n中序序列:");Inorder(BTree);printf("\n后序序列:");Postorder(BTree);printf("\n树的⾼度为:%d" , getHeight(BTree));return 0;}// ABC##DE##F##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)实现该图的拓扑排序算法。

北京师范大学《数据结构》课程教学大纲

北京师范大学《数据结构》课程教学大纲

北京师范大学《数据结构》课程教学大纲一、课程基本信息中文名称: 数据结构英文名称:Data Structure课程类别(公共任选课、学科基础课、专业方向课):学科基础课学分: 4学时: 48+32建议开设学期:2 开课单位建议:信息科学与技术学院主讲教师:(姓名) 沈复兴(性别)男(职称) (学科方向)教授 计算机软件郑新 女 副教授 计算机应用肖永康 男 讲师 计算机应用二、课程目标:本课程的主要目标是使学生深入了解数据结构的思想和数据结构的实现方法,特别是数据结构在实际工作中的应用和技术。

本课程追求理论联系实际,实践教学与相应的教学内容相呼应。

在形式上,灵活多样地采取了实践、拓展性学习、报告会等多种形式,目的在于加深学生对所学内容的理解,发展学生从事发展算法与程序设计研究和实践的能力,努力做到学以致用,同时激发学生的学习兴趣和主动参与精神,更好地掌握和运用所学习的知识。

三、课程内容与主要学习材料(含教材及参考书目)课程内容:第一章 绪论1. 教学内容:♦数据结构的一些基本概念:数据、数据元素、数据的逻辑结构、物理结构、算法等。

♦抽象数据类型。

♦描述算法的程序语言(C++)。

♦算法时间复杂度和空间复杂度的分析。

2. 教学目的及要求♦掌握数据、数据对象、数据元素、数据结构、数据的逻辑结构与物理结构、逻辑结构与物理结构间的关系等数据结构的基本概念;♦了解数据类型、抽象数据类型、数据抽象和信息隐蔽原则以及面向对象这种数据抽象实现方法♦了解算法的定义、算法的特性、算法的时间代价、算法的空间代价♦掌握用C++语言描述算法的方法,能够使用C++语言编写程序3. 教学重点数据结构的概念;算法分析;C++语言。

4. 学时分配本章共教授4学时.第二章数组1. 教学内容♦线性表的基本概念♦顺序表:顺序表的定义和特点;顺序表的类定义;顺序表的查找、插入和删除;使用顺序表的事例;顺序表复杂度分析♦特殊矩阵的压缩存储:特殊矩阵定义、稀疏矩阵类定义、矩阵转置与快速转置、矩阵乘法与输出♦字符串:字符串类型定义;字符串操作的实现;字符串的模式匹配2. 教学目的及要求♦了解线性表的逻辑结构特性,以及线性表的两种存储实现方式♦熟练掌握顺序表的定义与实现,包括搜索、插入、删除算法的实现及其平均比较次数的计算,掌握应用顺序表作为集合的简单操作♦了解稀疏矩阵的定义及其数组实现♦掌握字符串的定义及实现3. 教学重点线性表的基本概念、顺序表的实现及应用4. 教学难点矩阵的快速转置及模式匹配改进5. 教学时间分配本章共教授4学时.第三章链表1.教学内容♦单链表:单链表的结构;单链表的类定义;单链表中的查找、插入与删除;带表头结点的单链表;单链表的游标类及静态链表♦循环链表:循环链表的类定义及操作;用循环链表解约瑟夫问题;♦多项式及其相加:多项式的链表表示类定义;多项式的加法♦双向链表:双向链表的类定义及操作♦稀疏矩阵:稀疏矩阵的正交链表表示法及建立和删除操作2.教学目的及要求♦了解链表与数组一样,是一种实现级结构。

数据结构课程设计二 叉 树 遍 历 及 应 用

数据结构课程设计二 叉 树 遍 历 及 应 用

实验报告课程:数据结构课程设计设计题目:二叉树遍历及应用学号:班级:软件11k1姓名: 南方小羊指导教师:刘军二叉树的遍历1、问题描述利用先序遍历建立一棵二叉树,并分别用前序、中序、后序遍历该二叉树2、节点形式Lchild data Rchild3、说明(1)输入数据:1,2,3,0,0,4,0,0,5,0,0其中“0”表示空子树。

(2)输出数据:先序:1,2,3,4,5中序:3,2,4,1,5后序:3,4,2,5,1二叉树的应用1、问题描述运用二叉树的遍历的算法,编写算法分别实现如下功能。

(1)求出二叉树中的结点的总数。

(2)求出二叉树中的叶子数目。

(3)求出二叉树的深度。

运用上题所建立的二叉树,求出其结点总数、叶子数目、深度,最后释放所有结点。

二叉树结点结构中包数据域(data),指针域(*lchild,*rchild)。

结点结构的代码如下:typedef struct tree{int data;struct tree *lchild,*rchild;}*bitree;本实例使用的是二叉树,首先建立头结点,并且保存数据,然后根据递归方法,分别建立其左右孩子结点,且左右孩子结点的指针域指向空。

先序递归遍历时,输出第一个根结点数据,然后分别遍历左子树再遍历右子树,中序遍历,先访问根结点的左子树输出数据,再输出根结点的数据,再访问右子树,后序遍历先访问根结点的右子树,再访问根结点,再访问左子树输出。

统计二叉树叶子的个数可以看成一个遍历问题,访问一个结点,判断该结点是否为叶子,如果是将叶子树加1,可以采用任何遍历实现,求二叉树的深度是假设根结点为第一层的结点,所有K层结点的左右孩子在K+1层,所以可以通过先序遍历计算二叉树中每个结点的层数,其中最大的就是二叉树的深度。

四、实验心得:树结构是数据结构课程的典型内容,而且综合使用了多种逻辑结构,具有代表性,可以锻炼个人编程能力。

在刚开始选题后,我感觉无从下手,一是因为没有实践经验,二是因为对数据结构课程的内容没有把握到位,然后在参考一些专业书籍并且学习了之前其他人的课程设计,才逐渐可以上手去自己做。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

##大学数据结构课程设计报告题目:图的遍历和生成树求解院(系):计算机工程学院学生:班级:学号:起迄日期: 2011.6.20指导教师:2010—2011年度第 2 学期一、需求分析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;}}else{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.主要函数的程序流程图,实现设计中主程序和其他子模块的算法,以流程图的形式表示。

相关文档
最新文档