图的深度广度遍历(算法与数据结构课程设计)

合集下载

图的遍历算法

图的遍历算法

1图的遍历问题在实践中常常遇到这样的问题:给定n个点,从任一点出发对所有的点访问一次并且只访问一次。

如果用图中的顶点表示这些点,图中的边表示可能的连接,那么这个问题就可以表示成图的遍历问题,即从某个顶点出发,沿着某条搜索路径对图中每个顶点各做一次且仅做一次访问。

图的遍历操作和树的遍历操作功能相似,是图的一种基本操作,图的许多其它操作都是建立在遍历操作的基础上。

由于图结构本身的复杂性,所以图的遍历操作也比较复杂,主要表现在以下几个方面:(1) 在图结构中,没有一个确定的首结点,图中任意一个顶点都可以作为第一个被访问的结点。

(2) 在非连通图中,从一个顶点出发,只能够访问它所在的连通分量上的所有顶点,因此,还需要考虑如何选取下一个出发点以访问图中其余的连通分量。

(3) 在图结构中,如果有回路存在,那么一个顶点被访问后,有可能沿回路又回到该顶点。

⑷在图结构中,一个顶点可以和其它多个顶点相连,当这样的顶点访问过后,存在如何选取下一个要访问的顶点的问题。

基于以上分析,图的遍历方法目前有深度优先搜索(DFS)和广度优先搜索(BFS)两种算法。

下面将介绍两种算法的实现思路,分析算法效率并编程实现。

1.1深度优先搜索算法深度优先搜索算法是树的先根遍历的推广,它的实现思想是:从图G的某个顶点V o出发,访问V o,然后选择一个与V o相邻且没被访问过的顶点V i访问,再从V i出发选择一个与V i相邻且未被访问的顶点V j进行访问,依次继续。

如果当前被访问过的顶点的所有邻接顶点都已被访问,贝U退回已被访问的顶点序列中最后一个拥有未被访问的相邻顶点的顶点W,从W出发按同样的方法向前遍历,直到图中所有顶点都被访问。

其递归算法如下:Boolean visited[MAX_VERTEX_NUM]; // 访问标志数组Status (*VisitFunc)(int v); //VisitFunc是访问函数,对图的每个顶点调用该函数void DFSTraverse (Graph G Status(*Visit)(i nt v)){VisitF unc = Visit;for(v=0; vvG.vex num; ++v)visited[v] = FALSE; //访问标志数组初始化for(v=0; v<G .vex num; ++v)if(!visited[v])DFS(G v); //对尚未访问的顶点调用DFS}void DFS(Graph G int v){ //从第v个顶点出发递归地深度优先遍历图Gvisited[v]=TRUE; VisitFunc(v); // 访问第v 个顶点for(w=FirstAdjVex(G ,v); w>=0;w=NextAdjVex(G ,v,w))//FirstAdjVex返回v的第一个邻接顶点,若顶点在G中没有邻接顶点,则返回空(0)。

数据结构的课程设计

数据结构的课程设计

数据结构的课程设计一、课程目标知识目标:1. 理解数据结构的基本概念,掌握线性表、树、图等常见数据结构的特点与应用场景。

2. 学会分析不同数据结构的存储方式和操作方法,并能运用到实际问题的解决中。

3. 掌握排序和查找算法的基本原理,了解其时间复杂度和空间复杂度。

技能目标:1. 能够运用所学数据结构知识,解决实际问题,提高编程能力。

2. 能够运用排序和查找算法,优化程序性能,提高解决问题的效率。

3. 能够运用数据结构知识,分析并解决复杂问题,培养逻辑思维能力和创新意识。

情感态度价值观目标:1. 培养学生对数据结构学科的兴趣,激发学习热情,形成主动探索和积极进取的学习态度。

2. 增强学生的团队协作意识,培养合作解决问题的能力,提高沟通表达能力。

3. 培养学生的抽象思维能力,使其认识到数据结构在计算机科学中的重要性,激发对计算机科学的热爱。

本课程针对高中年级学生,结合学科特点和教学要求,注重理论与实践相结合,培养学生的编程能力和逻辑思维能力。

通过本课程的学习,使学生能够掌握数据结构的基本知识,提高解决实际问题的能力,同时培养良好的学习态度和价值观。

在教学过程中,将目标分解为具体的学习成果,以便进行后续的教学设计和评估。

二、教学内容1. 数据结构基本概念:介绍数据结构的概念、作用和分类,重点讲解线性结构(线性表、栈、队列)和非线性结构(树、图)的特点。

2. 线性表:讲解线性表的顺序存储和链式存储结构,以及相关操作(插入、删除、查找等)。

3. 栈和队列:介绍栈和队列的应用场景、存储结构及相关操作。

4. 树和二叉树:讲解树的定义、性质、存储结构,二叉树的遍历算法及线索二叉树。

5. 图:介绍图的定义、存储结构(邻接矩阵和邻接表)、图的遍历算法(深度优先搜索和广度优先搜索)。

6. 排序算法:讲解常见排序算法(冒泡排序、选择排序、插入排序、快速排序等)的原理、实现及性能分析。

7. 查找算法:介绍线性查找、二分查找等查找算法的原理及实现。

图的遍历 实验报告

图的遍历  实验报告

图的遍历实验报告一、引言图是一种非线性的数据结构,由一组节点(顶点)和节点之间的连线(边)组成。

图的遍历是指按照某种规则依次访问图中的每个节点,以便获取或处理节点中的信息。

图的遍历在计算机科学领域中有着广泛的应用,例如在社交网络中寻找关系紧密的人员,或者在地图中搜索最短路径等。

本实验旨在通过实际操作,掌握图的遍历算法。

在本实验中,我们将实现两种常见的图的遍历算法:深度优先搜索(DFS)和广度优先搜索(BFS),并比较它们的差异和适用场景。

二、实验目的1. 理解和掌握图的遍历算法的原理与实现;2. 比较深度优先搜索和广度优先搜索的差异;3. 掌握图的遍历算法在实际问题中的应用。

三、实验步骤实验材料1. 计算机;2. 编程环境(例如Python、Java等);3. 支持图操作的相关库(如NetworkX)。

实验流程1. 初始化图数据结构,创建节点和边;2. 实现深度优先搜索算法;3. 实现广度优先搜索算法;4. 比较两种算法的时间复杂度和空间复杂度;5. 比较两种算法的遍历顺序和适用场景;6. 在一个具体问题中应用图的遍历算法。

四、实验结果1. 深度优先搜索(DFS)深度优先搜索是一种通过探索图的深度来遍历节点的算法。

具体实现时,我们可以使用递归或栈来实现深度优先搜索。

算法的基本思想是从起始节点开始,选择一个相邻节点进行探索,直到达到最深的节点为止,然后返回上一个节点,再继续探索其他未被访问的节点。

2. 广度优先搜索(BFS)广度优先搜索是一种逐层遍历节点的算法。

具体实现时,我们可以使用队列来实现广度优先搜索。

算法的基本思想是从起始节点开始,依次遍历当前节点的所有相邻节点,并将这些相邻节点加入队列中,然后再依次遍历队列中的节点,直到队列为空。

3. 时间复杂度和空间复杂度深度优先搜索和广度优先搜索的时间复杂度和空间复杂度如下表所示:算法时间复杂度空间复杂度深度优先搜索O(V+E) O(V)广度优先搜索O(V+E) O(V)其中,V表示节点的数量,E表示边的数量。

算法与数据结构课设(有向图,无向图,有向网,无向网)

算法与数据结构课设(有向图,无向图,有向网,无向网)

算法与数据结构课程设计报告系(院):计算机科学学院专业班级:教技1001姓名:李##学号: ******### 指导教师:***设计时间:2012.6.16 - 2012.6.24设计地点:4号楼2号机房目录一、设计方案 (1)二、实现过程以及代码 (2)三、测试 (20)四、结论和分析 (23)五、难点和收获 (23)一、 设计方案1.程序设计基本过程:拿到课程设计任务书,按照要求,需要设计有向图、有向网、无向图 、无向网四种图,以及邻接矩阵、邻接表两种数据存储结构,三层以上的显示菜单。

图的操作中又包含了有关线性表、栈和队列的基本操作。

由于显示菜单已给出,剩下的任务就是把函数写入其中。

2.程序流程图:预定义 定义结构体 定义变量 各种函数3.程序设计的原理:图的操作都是以两种存储结构为基础的:邻接矩阵存储结构和邻接表存储结构,如有向图,有向网,无向图,无向网的创建,其他的操作都是在四种图创建后才开始进行的。

所以,首先必须理解两种存储结构的定义。

图的邻接矩阵存储结构即图的数组表示法。

用两个数组分别存储数据元素(如顶点)的信息和数据元素之间的关系(如边或弧)的信息。

用邻接矩阵存储结构的图具有以下几点特征:(一):顶点数:vexnum ,边(弧)数:arcnum ,图的种类:kind ;(二):邻接矩阵:arcs(1顶点关系类型:adj 2相关信息:*info);(三):顶点向量(顶点名):vexs[];其优点是以二维数组表示有n 个顶点的图时,需存放n 个顶点的信息和n*n 条弧的信息存储量。

借助邻接矩阵容易判定任意两个顶点之间是否有边或弧相连,并容易求出各个顶点的度。

缺点是时间复杂度是O (n*n ),例如,构造一个具有n 个顶点和e 条边的无向网的时间复杂度为O (n*n+e*n )。

图的邻接表存储结构是图的一种链式存储结构。

对图中的每个顶点建立一个单链表,每个结点由三个域组成,邻接点域adjvex (弧尾在邻接表链表中的位序),链域nextarc (下一条弧),数据域info(权值)。

图的遍历的实验报告

图的遍历的实验报告

图的遍历的实验报告图的遍历的实验报告一、引言图是一种常见的数据结构,它由一组节点和连接这些节点的边组成。

图的遍历是指从图中的某个节点出发,按照一定的规则依次访问图中的所有节点。

图的遍历在许多实际问题中都有广泛的应用,例如社交网络分析、路线规划等。

本实验旨在通过实际操作,深入理解图的遍历算法的原理和应用。

二、实验目的1. 掌握图的遍历算法的基本原理;2. 实现图的深度优先搜索(DFS)和广度优先搜索(BFS)算法;3. 比较并分析DFS和BFS算法的时间复杂度和空间复杂度。

三、实验过程1. 实验环境本实验使用Python编程语言进行实验,使用了networkx库来构建和操作图。

2. 实验步骤(1)首先,我们使用networkx库创建一个包含10个节点的无向图,并添加边以建立节点之间的连接关系。

(2)接下来,我们实现深度优先搜索算法。

深度优先搜索从起始节点开始,依次访问与当前节点相邻的未访问过的节点,直到遍历完所有节点或无法继续访问为止。

(3)然后,我们实现广度优先搜索算法。

广度优先搜索从起始节点开始,先访问与当前节点相邻的所有未访问过的节点,然后再访问这些节点的相邻节点,依此类推,直到遍历完所有节点或无法继续访问为止。

(4)最后,我们比较并分析DFS和BFS算法的时间复杂度和空间复杂度。

四、实验结果经过实验,我们得到了如下结果:(1)DFS算法的时间复杂度为O(V+E),空间复杂度为O(V)。

(2)BFS算法的时间复杂度为O(V+E),空间复杂度为O(V)。

其中,V表示图中的节点数,E表示图中的边数。

五、实验分析通过对DFS和BFS算法的实验结果进行分析,我们可以得出以下结论:(1)DFS算法和BFS算法的时间复杂度都是线性的,与图中的节点数和边数呈正比关系。

(2)DFS算法和BFS算法的空间复杂度也都是线性的,与图中的节点数呈正比关系。

但是,DFS算法的空间复杂度比BFS算法小,因为DFS算法只需要保存当前路径上的节点,而BFS算法需要保存所有已访问过的节点。

数据结构课程设计python

数据结构课程设计python

数据结构课程设计python一、课程目标知识目标:1. 理解数据结构的基本概念,掌握常用数据结构如列表、元组、字典和集合的特点及应用场景。

2. 学习并掌握栈和队列的操作原理及其在Python中的实现方法。

3. 掌握树和图的基本概念,了解二叉树、遍历算法及图的表示方法。

技能目标:1. 能够运用Python语言实现基本数据结构,并对其进行增、删、改、查等操作。

2. 能够利用栈和队列解决实际问题,如递归、函数调用栈、任务调度等。

3. 能够运用树和图解决实际问题,如查找算法、路径规划等。

情感态度价值观目标:1. 培养学生严谨的逻辑思维,提高分析问题和解决问题的能力。

2. 激发学生对数据结构和算法的兴趣,培养良好的编程习惯。

3. 引导学生认识到数据结构在实际应用中的重要性,增强学习热情和责任感。

课程性质:本课程为高年级数据结构课程,旨在使学生掌握Python语言实现数据结构的方法,提高编程能力和解决问题的能力。

学生特点:学生具备一定的Python编程基础,具有较强的逻辑思维能力,对数据结构有一定的了解。

教学要求:结合实际案例,采用任务驱动法,引导学生通过实践掌握数据结构的基本原理和应用方法。

注重培养学生的动手能力和团队协作精神,提高学生的综合素质。

通过本课程的学习,使学生能够具备独立设计和实现小型项目的能力。

二、教学内容1. 数据结构基本概念:介绍数据结构的概念、作用和分类,结合Python语言特点,分析各类数据结构在实际应用中的优势。

- 列表、元组、字典和集合的原理与应用- 栈与队列的操作原理及实现2. 线性表:讲解线性表的概念,重点掌握顺序表和链表的操作方法。

- 顺序表和链表的实现及操作- 线性表的查找和排序算法3. 树与二叉树:介绍树的基本概念,重点讲解二叉树的结构及其遍历算法。

- 树的基本概念和表示方法- 二叉树的性质、存储结构、遍历方法4. 图:讲解图的基本概念,掌握图的存储结构及遍历方法。

- 图的基本概念和表示方法- 图的遍历算法(深度优先搜索、广度优先搜索)- 最短路径和最小生成树算法5. 算法分析与设计:结合实例,分析算法性能,掌握基本的算法设计方法。

数据结构课设——有向图的深度、广度优先遍历及拓扑排序

数据结构课设——有向图的深度、广度优先遍历及拓扑排序

数据结构课设——有向图的深度、⼴度优先遍历及拓扑排序任务:给定⼀个有向图,实现图的深度优先, ⼴度优先遍历算法,拓扑有序序列,并输出相关结果。

功能要求:输⼊图的基本信息,并建⽴图存储结构(有相应提⽰),输出遍历序列,然后进⾏拓扑排序,并测试该图是否为有向⽆环图,并输出拓扑序列。

按照惯例,先上代码,注释超详细:#include<stdio.h>#include<stdlib.h>#include<malloc.h>#pragma warning(disable:4996)#define Max 20//定义数组元素最⼤个数(顶点最⼤个数)typedef struct node//边表结点{int adjvex;//该边所指向结点对应的下标struct node* next;//该边所指向下⼀个结点的指针}eNode;typedef struct headnode//顶点表结点{int in;//顶点⼊度char vertex;//顶点数据eNode* firstedge;//指向第⼀条边的指针,边表头指针}hNode;typedef struct//邻接表(图){hNode adjlist[Max];//以数组的形式存储int n, e;//顶点数,边数}linkG;//以邻接表的存储结构创建图linkG* creat(linkG* g){int i, k;eNode* s;//边表结点int n1, e1;char ch;g = (linkG*)malloc(sizeof(linkG));//申请结点空间printf("请输⼊顶点数和边数:");scanf("%d%d", &n1, &e1);g->n = n1;g->e = e1;printf("顶点数:%d 边数:%d\n", g->n, g->e);printf("请输⼊顶点信息(字母):");getchar();//因为接下来要输⼊字符串,所以getchar⽤于承接上⼀条命令的结束符for (i = 0; i < n1; i++){scanf("%c", &ch);g->adjlist[i].vertex = ch;//获得该顶点数据g->adjlist[i].firstedge = NULL;//第⼀条边设为空}printf("\n打印顶点下标及顶点数据:\n");for (i = 0; i < g->n; i++)//循环打印顶点下标及顶点数据{printf("顶点下标:%d 顶点数据:%c\n", i, g->adjlist[i].vertex);}getchar();int i1, j1;//相连接的两个顶点序号for (k = 0; k < e1; k++)//建⽴边表{printf("请输⼊对<i,j>(空格分隔):");scanf("%d%d", &i1, &j1);s = (eNode*)malloc(sizeof(eNode));//申请边结点空间s->adjvex = j1;//边所指向结点的位置,下标为j1s->next = g->adjlist[i1].firstedge;//将当前s的指针指向当前顶点上指向的结点g->adjlist[i1].firstedge = s;//将当前顶点的指针指向s}return g;//返回指针g}int visited[Max];//标记是否访问void DFS(linkG* g, int i)//深度优先遍历{eNode* p;printf("%c ", g->adjlist[i].vertex);visited[i] = 1;//将已访问过的顶点visited值改为1p = g->adjlist[i].firstedge;//p指向顶点i的第⼀条边while (p)//p不为NULL时(边存在){if (visited[p->adjvex] != 1)//如果没有被访问DFS(g, p->adjvex);//递归}p = p->next;//p指向下⼀个结点}}void DFSTravel(linkG* g)//遍历⾮连通图{int i;printf("深度优先遍历;\n");//printf("%d\n",g->n);for (i = 0; i < g->n; i++)//初始化为0{visited[i] = 0;}for (i = 0; i < g->n; i++)//对每个顶点做循环{if (!visited[i])//如果没有被访问{DFS(g, i);//调⽤DFS函数}}}void BFS(linkG* g, int i)//⼴度优先遍历{int j;eNode* p;int q[Max], front = 0, rear = 0;//建⽴顺序队列⽤来存储,并初始化printf("%c ", g->adjlist[i].vertex);visited[i] = 1;//将已经访问过的改成1rear = (rear + 1) % Max;//普通顺序队列的话,这⾥是rear++q[rear] = i;//当前顶点(下标)队尾进队while (front != rear)//队列⾮空{front = (front + 1) % Max;//循环队列,顶点出队j = q[front];p = g->adjlist[j].firstedge;//p指向出队顶点j的第⼀条边while (p != NULL){if (visited[p->adjvex] == 0)//如果未被访问{printf("%c ", g->adjlist[p->adjvex].vertex);visited[p->adjvex] = 1;//将该顶点标记数组值改为1rear = (rear + 1) % Max;//循环队列q[rear] = p->adjvex;//该顶点进队}p = p->next;//指向下⼀个结点}}}void BFSTravel(linkG* g)//遍历⾮连通图{int i;printf("⼴度优先遍历:\n");for (i = 0; i < g->n; i++)//初始化为0{visited[i] = 0;}for (i = 0; i < g->n; i++)//对每个顶点做循环{if (!visited[i])//如果没有被访问过{BFS(g, i);//调⽤BFS函数}}}//因为拓扑排序要求⼊度为0,所以需要先求出每个顶点的⼊度void inDegree(linkG* g)//求图顶点⼊度{eNode* p;int i;for (i = 0; i < g->n; i++)//循环将顶点⼊度初始化为0{g->adjlist[i].in = 0;}for (i = 0; i < g->n; i++)//循环每个顶点{p = g->adjlist[i].firstedge;//获取第i个链表第1个边结点指针while (p != NULL)///当p不为空(边存在){g->adjlist[p->adjvex].in++;//该边终点结点⼊度+1p = p->next;//p指向下⼀个边结点}printf("顶点%c的⼊度为:%d\n", g->adjlist[i].vertex, g->adjlist[i].in);}void topo_sort(linkG *g)//拓扑排序{eNode* p;int i, k, gettop;int top = 0;//⽤于栈指针的下标索引int count = 0;//⽤于统计输出顶点的个数int* stack=(int *)malloc(g->n*sizeof(int));//⽤于存储⼊度为0的顶点for (i=0;i<g->n;i++)//第⼀次搜索⼊度为0的顶点{if (g->adjlist[i].in==0){stack[++top] = i;//将⼊度为0的顶点进栈}}while (top!=0)//当栈不为空时{gettop = stack[top--];//出栈,并保存栈顶元素(下标)printf("%c ",g->adjlist[gettop].vertex);count++;//统计顶点//接下来是将邻接点的⼊度减⼀,并判断该点⼊度是否为0p = g->adjlist[gettop].firstedge;//p指向该顶点的第⼀条边的指针while (p)//当p不为空时{k = p->adjvex;//相连接的顶点(下标)g->adjlist[k].in--;//该顶点⼊度减⼀if (g->adjlist[k].in==0){stack[++top] = k;//如果⼊度为0,则进栈}p = p->next;//指向下⼀条边}}if (count<g->n)//如果输出的顶点数少于总顶点数,则表⽰有环{printf("\n有回路!\n");}free(stack);//释放空间}void menu()//菜单{system("cls");//清屏函数printf("************************************************\n");printf("* 1.建⽴图 *\n");printf("* 2.深度优先遍历 *\n");printf("* 3.⼴度优先遍历 *\n");printf("* 4.求出顶点⼊度 *\n");printf("* 5.拓扑排序 *\n");printf("* 6.退出 *\n");printf("************************************************\n");}int main(){linkG* g = NULL;int c;while (1){menu();printf("请选择:");scanf("%d", &c);switch (c){case1:g = creat(g); system("pause");break;case2:DFSTravel(g); system("pause");break;case3:BFSTravel(g); system("pause");break;case4:inDegree(g); system("pause");break;case5:topo_sort(g); system("pause");break;case6:exit(0);break;}}return0;}实验⽤图:运⾏结果:关于深度优先遍历 a.从图中某个顶点v 出发,访问v 。

《数据结构课程设计》指导书

《数据结构课程设计》指导书

《数据结构》课程设计指导书沈阳理工大学.信息学院2013.11.1一.目的与意义软件设计能力对计算机专业的学生是很重要。

通过数据结构的学习,使学生对软件编程能力有一定的提高。

数据结构课程设计是锻炼学生在进一步掌握模块化、结构化程序设计的方法的同时,培养学生运用已学知识分析问题、解决问题及编写实用程序的能力,通过对线性化、层次化、网络化数据结构的了解进一步掌握自然数据的结构方式及组织方式,让学生深入体会存储在计算机中的数据及程序中如何运用数据实现编程。

主要目的如下:1.通过本课程设计使学生对面向对象的设计过程有初的认识,并对面向对象的高能语言的学习打下基础,2.通过不同类型的程序设计使学生进一步掌握数据的几种不同的组织和存储方式,为高级编程做准备,3.为专业课的深入学习和毕业设计打基础二.任务和要求分析每一组题目,按要求完成相应的题目:1.题目参照附录中《数据结构课程设计》题目选题。

2. 要求:1)对相应的题目进行算法设计2)编写源代码3)上机调试4)显示调试结果5)写出实验总结3.课程设计说明书设计完成后,将自己选定的题目按上述要求完成课程设计说明书。

课程设计说明书内容包含:题目、要求、初步设计(可以是流程图、功能模块图)、详细设计、程序代码、测试数据、运行结果、遇到的问题及总结几部分。

三.进度安排设计总学时为2周第一周:查阅资料、小组讨论、进行模块划分写出分析报告,画N-S结构化框图,编写程序清单,上机调试.第二周周四、五:验收(计算机机房),并将课程设计报告交上来.四.考核标准与成绩评定方式成绩评定有如下几项参考:1.初步设计内容的考核:是否有查阅资料能力?是否有设计思想?2.程序编码能力调试能力的考核:程序是否清晰、易读?在技算计上是否可独立完成程序的调试,是否熟练?3.说明书质量的考核:设计结构是否合理?叙述是否正确?方案是否可行?4.答辩:设计结果的调试能力,对自己设计是否熟练?5.出勤率极平时表现的考核:出勤超过2次不到者成绩为不及格。

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

图的操作一、问题描述图是一种较线性表和树更为复杂的数据结构。

在图形结构中,节点间的关系可以是任意的,图中任意两个数据元素之间都可以相关。

由此,图的应用极为广泛。

现在邻接矩阵和邻接表的存储结构下,完成图的深度、广度遍历。

二、基本要求1、选择合适的存储结构完成图的建立;2、建立图的邻接矩阵,能按矩阵方式输出图,并在此基础上,完成图的深度和广度遍历,输出遍历序列;3、建立图的邻接表,并在此基础上,完成图的深度和广度遍历,输出遍历序列;三、测试数据四、算法思想1、邻接矩阵顶点向量的存储。

用两个数组分别存储数据(定点)的信息和数据元素之间的关系(边或弧)的信息。

2、邻接表邻接表是图的一种链式存储结构。

在邻接表中,对图中每个定点建立一个单链表,第i 个单链表中的节点表示依附于定点vi的边。

每个节点由3个域组成,其中邻接点域(adjvex)指示与定点vi邻接的点在图中的位置,链域(nextarc)指示下一条边或弧的节点;数据域(info)存储和边或弧相关的信息,如权值等。

每个链表上附设一个头节点。

在表头节点中,除了设有链域(firstarc)指向链表中第一个节点之外,还设有存储定点vi的名或其他有关信息的数据域(data)。

3、图的深度遍历深度优先搜索遍历类似于树的先根遍历,是树的先跟遍历的推广。

假设初始状态是图中所有顶点未曾被访问,则深度优先搜索可从图中某个顶点v出发,访问此顶点,然后依次从v的未被访问的邻接点出发深度优先遍历图,甚至图中所有和v相通的顶点都被访问到;若此时图中尚有顶点未被访问,则另选图中一个未曾被访问的顶点作起始点,重复上述过程,直至图中所有顶点都被访问到为止。

4、图的广度遍历广度优先遍历类似于树的按层次遍历过程。

假设从图中某顶点v出发,在访问了v之后依次访问v的各个未曾访问过的邻接点,然后分别从这些邻接点出发依次访问它们的邻接点,并使“先被访问的顶点的邻接点”先与“后被访问的顶点的邻接点”被访问,直至图中所有已被访问的顶点的邻接点都被访问到。

若此时图中尚有顶点未被访问,则另选图中一个曾被访问的顶点作起始点,重复上述过程,直至图中所有顶点都被访问到为止。

五、模块划分一、基于邻接矩阵的深广度遍历1.Status InitQueue(LinkQueue *Q)根据已知Q初始化队列2.Status QueueEmpty (LinkQueue Q)判断队列是否为空3.Status EnQueue(LinkQueue *Q, QElemType e)将e压入队尾4.Status DeQueue(LinkQueue *Q, QElemType *e)取队头元素e5.int LocateVex(MGraph G,VertexType v)定位定点v6.void CreateGraph(MGraph *G)建立无向图的邻接矩阵7.void PrintGraph(MGraph G)输出邻接矩阵的无向图8.int FirstAdjVex(MGraph G,int v)第一个邻接点的定位9.int NextAdjVex(MGraph G,int v,int w)查找下一个邻接点10.void Dfs(MGraph G, int v)实现图的一次遍历11.void DfsTraverse(MGraph G)实现图的深度遍历12.void BfsTraverse(MGraph G)实现图的广度遍历13.Main主函数二、基于邻接表实现图的深广度遍历1.Status InitQueue(LinkQueue *Q)根据已知Q初始化队列2.Status QueueEmpty (LinkQueue Q)判断队列是否为空3.Status EnQueue(LinkQueue *Q, QElemType e)将e压入队尾4.Status DeQueue(LinkQueue *Q, QElemType *e) 取队头元素e5.void createALGraph(ALGraph *G)建立无向图的邻接矩阵6.void PrintGraph(MGraph G)输出邻接矩阵的无向图7.int FirstAdjVex(MGraph G,int v)第一个邻接点的定位8.int NextAdjVex(MGraph G,int v,int w)查找下一个邻接点9.void Dfs(MGraph G, int v)实现图的一次深度遍历10.void DfsTraverse(MGraph G)实现图的深度遍历11.void BFS(ALGraph G, int v)实现图的一次广度遍历12.void BfsTraverse(MGraph G)实现图的广度遍历13.Void …………………………………Main主函数六、数据结构//(ADT)1、基于邻接矩阵的图的类型定义typedef struct ArcCell{ VRType adj; /*图中有1/0表示是否有边,网中表示边上的权值*/ /* InfoType *info; 与边相关的信息*/} ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];typedef struct{ VertexType vexs[MAX_VERTEX_NUM]; /*顶点向量*/AdjMatrix arcs; /*邻接矩阵*/int vexnum,arcnum; /*图中当前顶点数和边数*/ } MGraph;2、基于邻接表的图的类型定义typedef struct ArcNode{int adjvex;struct ArcNode *nextarc;}ArcNode; /*表节点*/typedef struct{TElemType data;ArcNode *firstarc;}VNode,AdjList[MAXVER]; /*表节点*/typedef struct{AdjList vertices;int vexnum,arcnum; /*图中当前顶点数和边数*/} ALGraph;七、源程序一、基于邻接矩阵的图的深度、广度遍历#include "stdlib.h"#include "stdio.h"#include "string.h"#define TRUE 1#define FALSE 0#define OVERFLOW -2#define OK 1#define ERROR 0typedef int Status;#define INFINITY INT_MAX /*最大值“无穷”*/#define MAX_VERTEX_NUM 20 /*最大顶点个数*/typedef int Boolean;typedef char VertexType[20];typedef int VRType;/**************以下为队列的操作************//****队列的类型定义****/typedef int QElemType;typedef struct QNode{QElemType data;struct QNode *next;} QNode, *QueuePtr;typedef struct{QueuePtr front;QueuePtr rear;} LinkQueue;/****初始化队列****/Status InitQueue(LinkQueue *Q){ (*Q).front=(*Q).rear=(QueuePtr)malloc(sizeof(QNode)); if(!(*Q).front) exit(OVERFLOW);(*Q).front->next=NULL;return OK; }/****判断队列是否为空****/Status QueueEmpty (LinkQueue Q){ if (Q.front==Q.rear)return TRUE;elsereturn FALSE; }/****入队列****/Status EnQueue(LinkQueue *Q, QElemType e){ QueuePtr p;p=(QueuePtr)malloc(sizeof(QNode));if (!p) exit(OVERFLOW);p->data=e; p->next=NULL;(*Q).rear->next=p;(*Q).rear=p;return OK; }/****出队列****/Status DeQueue(LinkQueue *Q, QElemType *e){ QueuePtr p;if ((*Q).front==(*Q).rear) return ERROR;p=(*Q).front->next;*e=p->data;(*Q).front->next=p->next;if ((*Q).rear==p) (*Q).rear=(*Q).front;free(p);return OK; }/**************以下为图的操作************//*图的类型定义*/typedef struct ArcCell{ VRType adj; /*图中有1/0表示是否有边,网中表示边上的权值*/ /* InfoType *info; 与边相关的信息*/} ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];typedef struct{ VertexType vexs[MAX_VERTEX_NUM]; /*顶点向量*/AdjMatrix arcs; /*邻接矩阵*/int vexnum,arcnum; /*图中当前顶点数和边数*/} MGraph;/* 顶点在顶点向量中的定位*/int LocateVex(MGraph G,VertexType v){ int i;for(i=0;i<G.vexnum;i++)if (strcmp(v,G.vexs[i])==0) break;return i;}/*建立无向图的邻接矩阵*/void CreateGraph(MGraph *G){ int i,j,k; VertexType v1,v2;printf("\nInput MG vexnum,arcnum:");scanf("%d,%d",&(*G).vexnum,&(*G).arcnum);printf("Input %d vexs:",(*G).vexnum);for(i=0;i<(*G).vexnum;i++) /*输入顶点向量*/ { scanf("%s",(*G).vexs[i]); }printf("vexs list\n");for(i=0;i<G->vexnum;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 %d arcs(vi vj):\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];}}/*按邻接矩阵方式输出无向图*/void PrintGraph(MGraph G){ int i,j;printf("\nMGraph:\n");for(i=0; i<G.vexnum; i++){ printf("%10s",G.vexs[i]);for(j=0; j<G.vexnum; j++)printf("%4d",G.arcs[i][j].adj);printf("\n");}}/* 查找第1个邻接点 */int FirstAdjVex(MGraph G,int v){ int j,p=-1;for(j=0;j<G.vexnum;j++)if (G.arcs[v][j].adj==1) {p=j; break;}return p;}/* 查找下一个邻接点 */int NextAdjVex(MGraph G,int v,int w){ int j,p=-1;for(j=w+1;j<G.vexnum;j++)if (G.arcs[v][j].adj==1) {p=j; break;}return p;}/*深度遍历*/Boolean visited[MAX_VERTEX_NUM]; /* 设置全局的访问标志数组 */void Dfs(MGraph G, int v){ int w;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);}void DfsTraverse(MGraph G){ int v;for (v=0; v<G.vexnum; v++)visited[v]=FALSE;for(v=0; v<G.vexnum; v++)if (!visited[v]) Dfs(G,v);}/* 广度遍历 */void BfsTraverse(MGraph G){ int v,u,w; LinkQueue Q;for(v=0; v<G.vexnum; v++) visited[v]=FALSE;InitQueue(&Q);for(v=0; v<G.vexnum; 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(){ int w;MGraph G;CreateGraph(&G);PrintGraph(G);printf("\nDfs:"); DfsTraverse(G); /* 深度遍历 */ printf("\nBfs:"); BfsTraverse(G); /* 广度遍历 */ }二:基于邻接表的图的深度、广度遍历#include "stdlib.h"#include "stdio.h"#include "string.h"#define MAXVER 21#define N 100typedef char TElemType[10];/*循环队列的操作*//****队列的类型定义****/typedef int ElemType;typedef struct{ElemType *base;int front,rear;}SqQueue;/****初始化队列****/void InitQueue(SqQueue *Q){Q->base=(ElemType *)malloc(N*sizeof(ElemType)); Q->front=Q->rear=0; }/****判断队列是否为空****/int QueueEmpty(SqQueue Q){if(Q.front==Q.rear)return 1;elsereturn 0;}/****入队列****/int EnQueue(SqQueue *Q,ElemType e){if((Q->rear+1)%N==Q->front)return 0;Q->base[Q->rear]=e;Q->rear=(Q->rear+1)%N;return 1;}/****出队列****/int DeQueue(SqQueue *Q,ElemType *e){if(Q->rear==Q->front)return 0;*e=Q->base[Q->front];Q->front=(Q->front+1)%N;return 1;}/*图的操作*//*图的类型定义*/typedef struct ArcNode{int adjvex;struct ArcNode *nextarc;}ArcNode;typedef struct{TElemType data;ArcNode *firstarc;}VNode,AdjList[MAXVER];typedef struct{AdjList vertices;int vexnum,arcnum;} ALGraph;/*建立无向图的邻接矩阵*/void createALGraph(ALGraph *G){int i, s, d;ArcNode *p,*q;printf("\nInput MG vexnum,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单链表的头结点后}}/*深度遍历*/int visited[MAXVER];//定义全局数组遍历visitedvoid dfs(ALGraph G, int v)//被遍历的图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所指表结点对应的邻接顶点未访问则递归地从该顶点出发调用dfsp=p->nextarc;}}void dfsTraverse(ALGraph G){int v;//遍历图之前初始化各未访问的顶点for(v=1; v<=G.vexnum; v++)visited[v]=0;//从各个未被访问过的顶点开始进行深度遍历for(v=1;v<=G.vexnum;v++)if(visited[v]==0) dfs(G,v);}/*广度遍历*/void BFS(ALGraph G, int v)//从顶点编号v出发,广度遍历邻接表存储的图G {SqQueue Q; 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;}}}void BFSTraverse(ALGraph G){int v;//遍历G以前,初始化visited数组为0for(v=1;v<=G.vexnum;v++)visited[v]=0;for(v=1;v<=G.vexnum;v++)if(visited[v]==0)BFS(G,v);}void main(){ALGraph G;createALGraph(&G);printf("深度遍历结果为:\n");dfsTraverse(G);printf("\n广度遍历结果为:\n");BFSTraverse(G);system("pause");}八、测试情况程序的测试结果如下:1、基于邻接矩阵的图的深度、广度遍历结果正确2、基于邻接表的图的深度、广度遍历结果正确九、参考文献1、严蔚敏,《数据结构 C语言》,清华大学出版社。

相关文档
最新文档