邻接矩阵表示图深度广度优先遍历
解释结构模型邻接矩阵

解释结构模型邻接矩阵结构模型(Structural Model)是指在软件工程中,用于描述系统的静态结构的一种模型。
它通常用于表示系统的组件、类、对象之间的静态关系以及它们的属性和行为。
结构模型可以帮助开发人员理解系统的组成部分以及它们之间的相互关系,从而更好地设计、开发和维护软件系统。
在结构模型中,最常用的表示方法是邻接矩阵(Adjacency Matrix)。
邻接矩阵是一种用来表示图形结构的矩阵。
图形结构是由节点和连接节点的边组成的。
邻接矩阵的行和列分别对应图的节点,矩阵中的元素表示节点之间是否存在边。
如果两个节点之间存在边,则对应矩阵元素的值为1;如果两个节点之间不存在边,则对应矩阵元素的值为0。
邻接矩阵可以提供关于图形结构的丰富信息。
通过分析矩阵的行和列,可以确定图中节点的数量、节点之间的连接关系、节点的度等。
邻接矩阵还可以用于进行图的遍历和算法,如深度优先(DFS)和广度优先(BFS)。
此外,邻接矩阵还可以用于解决一些图形相关的优化问题,如最短路径问题和最小生成树问题。
邻接矩阵在实际应用中有广泛的用途。
例如,在社交网络分析中,可以使用邻接矩阵来表示用户之间的关系,并通过矩阵的运算来发现社交网络中的社群结构。
在路由器和互联网中,邻接矩阵可以用来描述网络节点之间的物理连接,从而实现路由表的生成和更新。
邻接矩阵还可以用于解决诸如稀疏矩阵压缩和图形聚类等问题。
然而,邻接矩阵也存在着一些限制和不足之处。
首先,矩阵的大小由节点的数量决定,对于大型图形结构,矩阵会占用大量的内存空间。
其次,对于稀疏图,即节点之间的连接较少的情况,邻接矩阵会浪费大量的空间来表示不存在的边,从而造成存储的浪费。
此外,邻接矩阵在表示稀疏图时的运算效率较低,不适用于一些复杂的图形分析算法。
为了克服邻接矩阵的不足,还有其他的表示图形结构的方法,如邻接表(Adjacency List)和邻接多重表(Adjacency Multilist)。
数据结构第六-九章自测题及解答

一、概念题(每空0.5分,共45分)1.对于集合这逻辑结构来说,其中的数据元素之间也可以有各种各样的非逻辑关系,但任何一对数据元素之间没有________关系,即没有________关系。
2.查找表按其所包括的运算的不同分为________查找表和________查找表。
3.查找表中主关键字指的是________,次关键字指的是________。
4.静态查找表包括________、________、________三种基本运算。
5.动态查找表包括________、________、________、________、________五种基本运算。
6.假定key为主关键字,若顺序表中第n个元素的键值为K,则顺序查找算法的查找长度为1;若第1个元素的键值为K,则查找长度为________;若表中无键值等于K的元素,则查找长度为________。
7.二分查找在查找成功时的查找长度不超过________,其平均查找长度为________,当n较大时约等于________。
8.静态查找表的三种不同实现各有优缺点。
其中,________查找效率最低但限制最少。
________查找效率最高但限制最强。
而________查找则介于上述二者之间。
9.二叉搜索树是一种特殊的、增加了限制条件的二叉树,其限制条件是任一结点的键值________于其左孩子(及其子孙)的键值且________于其右孩子(及其子孙)的键值。
10. 在表示一棵二叉搜索树的二叉链表上,要找键值比某结点X的键值________的结点,只需通过结点X的左指针到它的左子树中去找。
11.中序遍历一棵二叉搜索树所得的结点访问序列是键值的________序列。
12.二叉搜索树上的查找长度不仅与________有关,也与二叉搜索树的________有关。
13.在随机情况下,含有n个结点的二叉搜索树的平均查找长度为________,其时间效率很高。
14.折半查找的查找效率与树的形态有关。
深度优先算法和广度优先算法的时间复杂度

深度优先算法和广度优先算法都是图搜索中常见的算法,它们具有不同的特点和适用场景。
在进行全面评估之前,让我们先来了解一下深度优先算法和广度优先算法的基本概念和原理。
### 1. 深度优先算法(Depth-First Search, DFS)深度优先算法是一种用于遍历或搜索树或图的算法。
其核心思想是从起始顶点出发,沿着一条路径直到末端,然后回溯,继续搜索下一条路径,直到所有路径都被探索。
在实际应用中,深度优先算法常常通过递归或栈来实现。
### 2. 广度优先算法(Breadth-First Search, BFS)广度优先算法也是一种用于遍历或搜索树或图的算法。
其核心思想是从起始顶点出发,依次遍历该顶点的所有相邻顶点,然后再以这些相邻顶点作为起点,继续遍历它们的相邻顶点,以此类推,直到所有顶点都被遍历。
在实际应用中,广度优先算法通常通过队列来实现。
### 3. 深度优先算法和广度优先算法的时间复杂度在实际应用中,我们经常需要对算法的时间复杂度进行分析。
针对深度优先算法和广度优先算法,它们的时间复杂度并不相同。
- 深度优先算法的时间复杂度:O(V + E),其中V为顶点数,E为边数。
在最坏的情况下,如果采用邻接矩阵来表示图的话,深度优先算法的时间复杂度为O(V^2);如果采用邻接表来表示图的话,时间复杂度为O(V + E)。
- 广度优先算法的时间复杂度:O(V + E),其中V为顶点数,E为边数。
无论采用邻接矩阵还是邻接表表示图,广度优先算法的时间复杂度都是O(V + E)。
### 4. 个人理解和观点在实际应用中,我们在选择使用深度优先算法还是广度优先算法时,需要根据具体的问题场景来进行选择。
如果要寻找图中的一条路径,或者判断两个节点之间是否存在路径,通常会选择使用深度优先算法;如果要寻找最短路径或者进行层次遍历,通常会选择使用广度优先算法。
深度优先算法和广度优先算法都是非常重要的图搜索算法,它们各自适用于不同的场景,并且具有不同的时间复杂度。
图的遍历操作实验报告

-实验三、图的遍历操作一、目的掌握有向图和无向图的概念;掌握邻接矩阵和邻接链表建立图的存储构造;掌握DFS及BFS对图的遍历操作;了解图构造在人工智能、工程等领域的广泛应用。
二、要求采用邻接矩阵和邻接链表作为图的存储构造,完成有向图和无向图的DFS 和BFS操作。
三、DFS和BFS 的根本思想深度优先搜索法DFS的根本思想:从图G中*个顶点Vo出发,首先访问Vo,然后选择一个与Vo相邻且没被访问过的顶点Vi访问,再从Vi出发选择一个与Vi相邻且没被访问过的顶点Vj访问,……依次继续。
如果当前被访问过的顶点的所有邻接顶点都已被访问,则回退到已被访问的顶点序列中最后一个拥有未被访问的相邻顶点的顶点W,从W出发按同样方法向前遍历。
直到图中所有的顶点都被访问。
广度优先算法BFS的根本思想:从图G中*个顶点Vo出发,首先访问Vo,然后访问与Vo相邻的所有未被访问过的顶点V1,V2,……,Vt;再依次访问与V1,V2,……,Vt相邻的起且未被访问过的的所有顶点。
如此继续,直到访问完图中的所有顶点。
四、例如程序1.邻接矩阵作为存储构造的程序例如#include"stdio.h"#include"stdlib.h"#define Ma*Verte*Num 100 //定义最大顶点数typedef struct{char ve*s[Ma*Verte*Num]; //顶点表int edges[Ma*Verte*Num][Ma*Verte*Num]; //邻接矩阵,可看作边表int n,e; //图中的顶点数n和边数e}MGraph; //用邻接矩阵表示的图的类型//=========建立邻接矩阵=======void CreatMGraph(MGraph *G){int i,j,k;char a;printf("Input Verte*Num(n) and EdgesNum(e): ");scanf("%d,%d",&G->n,&G->e); //输入顶点数和边数scanf("%c",&a);printf("Input Verte* string:");for(i=0;i<G->n;i++){scanf("%c",&a);G->ve*s[i]=a; //读入顶点信息,建立顶点表}for(i=0;i<G->n;i++)for(j=0;j<G->n;j++)G->edges[i][j]=0; //初始化邻接矩阵printf("Input edges,Creat Adjacency Matri*\n");for(k=0;k<G->e;k++) { //读入e条边,建立邻接矩阵 scanf("%d%d",&i,&j); //输入边〔Vi,Vj〕的顶点序号G->edges[i][j]=1;G->edges[j][i]=1; //假设为无向图,矩阵为对称矩阵;假设建立有向图,去掉该条语句}}//=========定义标志向量,为全局变量=======typedef enum{FALSE,TRUE} Boolean;Boolean visited[Ma*Verte*Num];//========DFS:深度优先遍历的递归算法======void DFSM(MGraph *G,int i){ //以Vi为出发点对邻接矩阵表示的图G进展DFS搜索,邻接矩阵是0,1矩阵 int j;printf("%c",G->ve*s[i]); //访问顶点Vivisited[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为新出发点}void DFS(MGraph *G){int i;for(i=0;i<G->n;i++)visited[i]=FALSE; //标志向量初始化for(i=0;i<G->n;i++)if(!visited[i]) //Vi未访问过DFSM(G,i); //以Vi为源点开场DFS搜索}//===========BFS:广度优先遍历=======void BFS(MGraph *G,int k){ //以Vk为源点对用邻接矩阵表示的图G进展广度优先搜索 int i,j,f=0,r=0;int cq[Ma*Verte*Num]; //定义队列for(i=0;i<G->n;i++)visited[i]=FALSE; //标志向量初始化for(i=0;i<G->n;i++)cq[i]=-1; //队列初始化printf("%c",G->ve*s[k]); //访问源点Vkvisited[k]=TRUE;cq[r]=k; //Vk已访问,将其入队。
深度与广度优先搜索:迷宫问题

《数据结构课程设计》报告题目:深度与广度优先搜索--迷宫问题专业计算机科学与技术学生姓名李柏班级B计算机115学号1110704512指导教师巩永旺完成日期2013年1月11日目录1简介 (1)2算法说明 (1)3测试结果 (3)4分析与探讨 (7)5小结 (9)附录 (10)附录1 源程序清单 (10)迷宫问题1 简介1、图的存储结构图的存储结构又称图的表示,其最常用的方法是邻接矩阵和邻接表。
无论采用什么存储方式,其目标总是相同的,既不仅要存储图中各个顶点的信息,同时还要存储顶点之间的所有关系。
2、图的遍历图的遍历就是从指定的某个顶点(称其为初始点)出发,按照一定的搜索方法对图中的所有顶点各做一次访问过程。
根据搜索方法不同,遍历一般分为深度优先搜索遍历和广度优先搜索遍历。
本实验中用到的是广度优先搜索遍历。
即首先访问初始点v i,并将其标记为已访问过,接着访问v i的所有未被访问过的邻接点,顺序任意,并均标记为已访问过,以此类推,直到图中所有和初始点v i有路径相通的顶点都被访问过为止。
鉴于广度优先搜索是将所有路径同时按照顺序遍历,直到遍历出迷宫出口,生成的路径为最短路径。
因此我们采用了广度优先搜索。
无论是深度优先搜索还是广度优先搜索,其本质都是将图的二维顶点结构线性化的过程,并将当前顶点相邻的未被访问的顶点作为下一个顶点。
广度优先搜索采用队列作为数据结构。
本实验的目的是设计一个程序,实现手动或者自动生成一个n×m矩阵的迷宫,寻找一条从入口点到出口点的通路。
具体实验内容如下:选择手动或者自动生成一个n×m的迷宫,将迷宫的左上角作入口,右下角作出口,设“0”为通路,“1”为墙,即无法穿越。
假设一只老鼠从起点出发,目的为右下角终点,可向“上、下、左、右、左上、左下、右上、右下”8个方向行走。
如果迷宫可以走通,则用“■”代表“1”,用“□”代表“0”,用“☆”代表行走迷宫的路径。
输出迷宫原型图、迷宫路线图以及迷宫行走路径。
数据结构:图

数据结构:图在计算机科学领域,数据结构是我们组织和存储数据的方式,以便能够高效地进行操作和处理。
而图,作为一种重要的数据结构,在许多应用中都发挥着关键作用。
想象一下,我们生活中的各种关系,比如朋友关系、交通网络、电路连接等等,这些都可以用图来表示。
图由顶点(也称为节点)和边组成。
顶点代表着事物或者对象,而边则表示顶点之间的关系。
比如说,在一个社交网络中,每个人可以看作是一个顶点,如果两个人是朋友,那么在他们对应的顶点之间就会有一条边。
这种直观的表示方式让我们能够清晰地理解和分析复杂的关系。
图有两种主要的表示方式:邻接矩阵和邻接表。
邻接矩阵就像是一个表格,行和列都对应着顶点,如果两个顶点之间有边相连,对应的位置就标记为 1,否则为 0 。
这种表示方式简单直观,但当顶点数量很多而边的数量相对较少时,会浪费大量的存储空间。
邻接表则是为每个顶点创建一个链表,链表中存储着与该顶点相邻的顶点。
这种方式在处理稀疏图(边的数量相对较少的图)时,能够节省大量的空间,并且在查找相邻顶点时也比较高效。
图的遍历是操作图的重要方式之一。
深度优先遍历就像是在迷宫中一直往前走,直到走不通了再回溯;而广度优先遍历则像是以一个点为中心,一层一层地向外扩展。
深度优先遍历通常使用递归的方式实现。
从一个起始顶点开始,沿着一条路径尽可能地深入,直到无法继续,然后回溯,尝试其他的路径。
这种遍历方式在搜索、查找路径等问题中经常被使用。
广度优先遍历则使用队列来实现。
先将起始顶点入队,然后依次取出队列头部的顶点,并将其相邻的未访问过的顶点入队。
这种方式常用于计算最短路径、层次遍历等问题。
图的应用非常广泛。
在网络路由中,通过构建网络的图模型,可以找到最优的数据包传输路径;在任务调度中,可以根据任务之间的依赖关系,使用图来安排任务的执行顺序;在地图导航中,城市和道路可以表示为图,从而为用户规划最佳的出行路线。
再比如,在人工智能中的搜索算法中,图可以用来表示状态空间。
算法设计:深度优先遍历和广度优先遍历

算法设计:深度优先遍历和广度优先遍历实现深度优先遍历过程1、图的遍历和树的遍历类似,图的遍历也是从某个顶点出发,沿着某条搜索路径对图中每个顶点各做一次且仅做一次访问。
它是许多图的算法的基础。
深度优先遍历和广度优先遍历是最为重要的两种遍历图的方法。
它们对无向图和有向图均适用。
注意:以下假定遍历过程中访问顶点的操作是简单地输出顶点。
2、布尔向量visited[0..n-1]的设置图中任一顶点都可能和其它顶点相邻接。
在访问了某顶点之后,又可能顺着某条回路又回到了该顶点。
为了避免重复访问同一个顶点,必须记住每个已访问的顶点。
为此,可设一布尔向量visited[0..n-1],其初值为假,一旦访问了顶点Vi之后,便将visited[i]置为真。
--------------------------深度优先遍历(Depth-First Traversal)1.图的深度优先遍历的递归定义假设给定图G的初态是所有顶点均未曾访问过。
在G中任选一顶点v为初始出发点(源点),则深度优先遍历可定义如下:首先访问出发点v,并将其标记为已访问过;然后依次从v出发搜索v的每个邻接点w。
若w未曾访问过,则以w为新的出发点继续进行深度优先遍历,直至图中所有和源点v有路径相通的顶点(亦称为从源点可达的顶点)均已被访问为止。
若此时图中仍有未访问的顶点,则另选一个尚未访问的顶点作为新的源点重复上述过程,直至图中所有顶点均已被访问为止。
图的深度优先遍历类似于树的前序遍历。
采用的搜索方法的特点是尽可能先对纵深方向进行搜索。
这种搜索方法称为深度优先搜索(Depth-First Search)。
相应地,用此方法遍历图就很自然地称之为图的深度优先遍历。
2、深度优先搜索的过程设x是当前被访问顶点,在对x做过访问标记后,选择一条从x出发的未检测过的边(x,y)。
若发现顶点y已访问过,则重新选择另一条从x出发的未检测过的边,否则沿边(x,y)到达未曾访问过的y,对y访问并将其标记为已访问过;然后从y开始搜索,直到搜索完从y出发的所有路径,即访问完所有从y出发可达的顶点之后,才回溯到顶点x,并且再选择一条从x出发的未检测过的边。
邻接矩阵

哈尔滨工业大学计算机科学与技术学院实验报告课程名称:数据结构与算法课程类型:必修实验项目名称:图实验题目:图的遍历班级:0703301学号:1070330101姓名:任冬伟设计成绩报告成绩指导老师一、实验目的1)掌握图的邻接矩阵表示2)熟练掌握图的深度优先和广度优先搜索3)熟悉队列的基本操作,完成广度优先搜索二、实验要求及实验环境1)本程序是对图的邻接矩阵表示,进行广度优先和深度优先搜索2)本程序要求输入图中结点个数及边条数,以字符输入顶点信息。
然后输入边信息3)对图实现深度优先搜索4)对图实现广度优先搜索三、设计思想(本程序中的用到的所有数据类型的定义,主程序的流程图及各程序模块之间的调用关系)1.数据类型定义1)邻接矩阵struct MTGraph{char vexlist[NumbersVertices]; //顶点表int edge[NumbersVertices][NumbersVertices]; //边表int n,e; //当前顶点和边的个数};2)队列struct celltype{int element;celltype *next;};Typedef celltype *ELE;struct QUEUE {ELE front;ELE rear;};2.基本操作1)建立邻接矩阵void CreateMGragh(MTGraph &G); //建立邻接矩阵2)搜索void DFS(MTGraph G, int i); //深度优先搜索void BFS(MTGraph G, int k); //广度优先搜索3)队列的基本操作void MakeNull(QUEUE &q); //初始化bool Empty(QUEUE q); //判空char Front(QUEUE q); //返回队首void EnQueue(int x,QUEUE &q); //进队操作void Delete(QUEUE &q); //删除3.主函数流程1)创建图的邻接矩阵表示,输入图中结点个数及边条数,以字符输入顶点信息。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
*问题描述:建立图的存储结构(图的类型可以是有向图、无向图、有向网、无向网,学生可以任选两种类型),能够输入图的顶点和边的信息,并存储到相应存储结构中,而后输出图的邻接矩阵。
1、邻接矩阵表示法:设G=(V,E)是一个图,其中V={V1,V2,V3…,Vn}。
G的邻接矩阵是一个他有下述性质的n阶方阵:1,若(Vi,Vj)∈E 或<Vi,Vj>∈E;A[i,j]={0,反之图5-2中有向图G1和无向图G2的邻接矩阵分别为M1和M2:M1=┌0 1 0 1 ┐│ 1 0 1 0 ││ 1 0 0 1 │└0 0 0 0 ┘M2=┌0 1 1 1 ┐│ 1 0 1 0 ││ 1 1 0 1 │└ 1 0 1 0 ┘注意无向图的邻接是一个对称矩阵,例如M2。
用邻接矩阵表示法来表示一个具有n个顶点的图时,除了用邻接矩阵中的n*n个元素存储顶点间相邻关系外,往往还需要另设一个向量存储n个顶点的信息。
因此其类型定义如下:VertexType vertex[MAX_VERTEX_NUM]; // 顶点向量AdjMatrix arcs; // 邻接矩阵int vexnum, arcnum; // 图的当前顶点数和弧(边)数GraphKind kind; // 图的种类标志若图中每个顶点只含一个编号i(1≤i≤vnum),则只需一个二维数组表示图的邻接矩阵。
此时存储结构可简单说明如下:type adjmatrix=array[1..vnum,1..vnum]of adj;利用邻接矩阵很容易判定任意两个顶点之间是否有边(或弧)相联,并容易求得各个顶点的度。
对于无向图,顶点Vi的度是邻接矩阵中第i行元素之和,即n nD(Vi)=∑A[i,j](或∑A[i,j])j=1 i=1对于有向图,顶点Vi的出度OD(Vi)为邻接矩阵第i行元素之和,顶点Vi 的入度ID(Vi)为第i列元素之和。
即n nOD(Vi)=∑A[i,j],OD(Vi)=∑A[j,i])j=1j=1用邻接矩阵也可以表示带权图,只要令Wij, 若<Vi,Vj>或(Vi,Vj)A[i,j]={∞, 否则。
其中Wij为<Vi,Vj>或(Vi,Vj)上的权值。
相应地,网的邻接矩阵表示的类型定义应作如下的修改:adj:weightype ; {weightype为权类型} 图5-6列出一个网和它的邻接矩阵。
┌∞31∞∞┐│∞∞51∞││∞∞∞∞∞││∞∞6∞∞│└∞322∞┘(a)网(b)邻接矩阵图5-6 网及其邻接矩阵对无向图或无向网络,由于其邻接矩阵是对称的,故可采用压缩存贮的方法,仅存贮下三角或上三角中的元素(但不含对角线上的元素)即可。
显然,邻接矩阵表示法的空间复杂度O(n2)。
无向网邻接矩阵的建立方法是:首先将矩阵A的每个元素都初始化成∞。
然后,读入边及权值(i,j,wij),将A的相应元素置成Wij。
2、图的遍历:*深度优先搜索深度优先搜索遍历类似于树的先根遍历,是树的先根遍历的推广。
假设初始状态是图中所有的顶点未曾被访问,则深度优先遍历可从图的某个顶点V出发,访问此顶点,然后依次从V的未被访问的邻接点出发深度优先遍历图,直至图中所有和V有路径相通的顶点都被访问到;若此时图中尚有顶点未被访问,则另选图中的一个未被访问的顶点,重复上述过程,直至图中所有顶点都被访问到为止。
以图7.13(a)中无向图G4为例,深度优先遍历图的过程如图7.13(b)所示。
假设从顶点V1出发进行搜索,在访问了顶点V1后,选择邻接点V2。
因为V2未曾访问,则从V2出发进行搜索。
依次类推,接着从V4,V8,V5出发进行搜索。
在访问了V5之后,由于V5的邻接点已都被访问,则搜索回到V8。
由于同样的理由,搜索继续回到V4,V2直至V1,此时由于V1的另一个邻接点为被访问,则搜索又从V 1到V3,再继续进行下去。
由此得到顶点的访问序列为:V1V2V4V8V5V3V6V7显然,这是一个递归的过程。
为了在遍历过程中便于区别顶点是否已被访问,需附设访问标志数组visted[0...n-1],其初值为0,一但某个顶点被访问,则其相应的分量置为1。
*广度优先搜索假设从图中某顶点v出发,在访问了v之后一次访问v的各个未曾访问的扩大邻接点,然后分别从这些邻接点出发依次访问他们的邻接点,并使“先被访问的邻接点”先于“后被访问的邻接点”被访问,直至图中所有已被访问的顶点的邻接点都被访问到。
若图中尚有顶点未被访问,则另选图中一个未曾被访问的顶点作起始点,重复上述过程,直到图中的顶点都被访问为止。
换句话说,广度优先遍历图的过程就是以v为起始点,有远至近,依次访问和v有路径相通且路径长度为1、2……的顶点。
例如,对图G4进行广度优先搜索遍历的过程如图7.13(3)所示,首先访问v1和v1的邻接点v2和v3,然后依次访问v2的邻接点v4和v5及v3的邻接点v6和v7,最后访问v4的邻接点v8。
由于这些顶点的邻接点均已被访问,并且图中所有顶点都被访问,由此完成了图的遍历。
得到的顶点访问序列为V1 V2V3V4V5V6V7V8和深度优先搜索类似,在遍历的过程中也需要一个访问标志数组。
并且,为了顺次访问路径长度为2、3、…的顶点,需附设队列以存储已被访问的路径长度为1、2…的顶点。
2、图的输出图的邻接矩阵是一个二维数组,运用for语句的嵌套依次输出。
主程序流程图图的构造流程图1、无向图邻接矩阵的建立算法如下:procedure build-graph; {建立无向图的邻接矩阵}beginfor i:=1 to n do read(G.vertex[i]);{读入n个顶点的信息}for i:=1 to n dofor j:=1 to e doG.arcs[i][j] =0;{将邻接矩阵的每个元素初始化成0 }for k:=1 to e do {e为边的数目}[ read(i,j,w) {读入边<i,j>和权}G.arcs[i][j]:=w]G.arcs[i][j]=G.arcs[i][i]{置对称弧}end;该算法的执行时间是O(n+n2+e),其中消耗在邻接矩阵初始化操作上的时间是O(n2),而e<n2,所以上述算法的时间复杂度是O(n2)。
2、无向网邻接矩阵的建立算法如下:procedure build-graph; {建立无向网的邻接矩阵}beginfor i:=1 to n do read(G.vertex[i]);{读入n个顶点的信息}for i:=1 to n dofor j:=1 to e doG.arcs[i][j] =maxint;{将邻接矩阵的每个元素初始化成maxint,计算机内∞用最大事数maxint表示} for k:=1 to e do {e为边的数目}[ read(i,j,w) {读入边<i,j>和权}G.arcs[i][j]:=w; G.arcs[i][j]:=w] end;该算法的执行时间是O(n+n2+e),其中消耗在邻接矩阵初始化操作上的时间是O(n2),而e<n2,所以上述算法的时间复杂度是O(n2)。
3、图的深度优先遍历算法分析beginfor i:=1 to n do(visited[i]){初始化标志数组}while (i<n){for:i=1 to n do{按要求访问邻接点}}end当用二维数组表示邻接矩阵作图的存储结构时,查找每个顶点的邻接点所需时间为O(n2),其中n为图中顶点数。
4、图的广度优先遍历算法分析beginfor i:=1 to n do(visited[i]){初始化标志数组}while (i<n){for:i=1 to n do{if…..if…..}}end二维数组表示邻接矩阵作图的存储结构,其中n为图中顶点数,查找每个顶点的邻接点所需时间为O(n2)。
#include<stdio.h>#include<malloc.h>#include<conio.h>#include<stdlib.h>#include<string.h>#define ERROR 0#define OK 1#define MAX_VERTEX_NUM 20 //定义最大值#define INFINITY 32768 //定义极大值#define MAX_INFO 20typedef int VrType; //定义新的类型typedef int InfoType;typedef char VertexType;typedef enum{DG,DN,UDG,UDN}GraphKind;//有向图,有向网,无向图,无向网typedef struct ArcCell{//邻接矩阵表示法的各个数据结构VrType adj; // 顶点关系类型。
对无权图,用或表示相邻否;对带权图,则为权值类型。
InfoType *info; // 该弧相关信息的指针} ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];typedef struct{VertexType vertex[MAX_VERTEX_NUM]; // 顶点向量AdjMatrix arcs; // 邻接矩阵int vexnum, arcnum; // 图的当前顶点数和弧(边)数GraphKind kind; // 图的种类标志} MGraph;typedef struct{//设置栈int elem1[MAX_VERTEX_NUM];int top;}SeqStack;int LocateVertex(MGraph G,VertexType v);void CreateUDG(MGraph &G);void CreateUDN(MGraph &G);void DepthFirstSearch1(MGraph G);void BreadthFirstSearch1(MGraph G);int CreateGraph(MGraph &G);void Display(MGraph G);/* Graph.cpp */int LocateVertex(MGraph G,VertexType v){//用于返回输弧端点所表示的数值int j=0,k;for(k=0;k<G.vexnum;++k)if(G.vertex[k]==v){j=k;break;}return(j);}void CreateUDG(MGraph &G){ // 采用数组(邻接矩阵)表示法,构造无向图int i,j,k,IncInfo;//i,j,k为计数器,IncInfo为标志符char ch; //用于吃掉多余的字符VertexType v1,v2; //用于放置输入的弧的两个顶点printf("请输入无向图G的顶点数,边数,弧是否含相关信息(是:,否:): \n"); scanf("%d,%d,%d",&G.vexnum,&G.arcnum,&IncInfo);ch=getchar(); //用于吃掉回车printf("请输入%d个顶点的值(1个字符,空格隔开):\n",G.vexnum);for(i=0;i<G.vexnum;++i) // 构造顶点向量{scanf("%c",&G.vertex[i]);ch=getchar();}printf("请输入%d条边的顶点顶点(以空格作为间隔): \n",G.arcnum);for(i=0;i<G.vexnum;++i) // 初始化邻接矩阵for(j=0;j<G.vexnum;++j){G.arcs[i][j].adj=0;G.arcs[i][j].info=NULL; // {adj,info}}for(k=0;k<G.arcnum;++k){scanf("%c %c",&v1,&v2);ch=getchar();// ch吃掉回车符i=LocateVertex(G,v1); j=LocateVertex(G,v2);if(IncInfo)scanf("%d",&G.arcs[i][j].info);G.arcs[i][j].adj=G.arcs[j][i].adj=1; // 置<v1,v2>的对称弧<v2,v1>}}//CreateUDGvoid CreateUDN(MGraph &G){ // 采用数组(邻接矩阵)表示法,构造无向网int i,j,k,w,IncInfo;//i,j,k为计数器,w用于放置权值,IncInfo为标志符char ch; //用于吃掉多余的字符VertexType v1,v2; //用于放置输入的弧的两个顶点printf("请输入无向图G的顶点数,边数,弧是否含相关信息(是:,否:):\n ");scanf("%d,%d,%d",&G.vexnum,&G.arcnum,&IncInfo);ch=getchar(); //用于吃掉回车printf("请输入%d个顶点的值(1个字符,空格隔开):\n",G.vexnum);for(i=0;i<G.vexnum;++i) // 构造顶点向量{scanf("%c",&G.vertex[i]);ch=getchar();}printf("请输入%d条边的顶点顶点(以空格作为间隔): \n",G.arcnum);for(i=0;i<G.vexnum;++i) // 初始化邻接矩阵for(j=0;j<G.vexnum;++j){G.arcs[i][j].adj=0;G.arcs[i][j].info=NULL; //{adj,info}}for(k=0;k<G.arcnum;++k){scanf("%c %c",&v1,&v2);ch=getchar();// ch吃掉回车符printf("请输入该边的权值: ");scanf("%d",&w);ch=getchar();i=LocateVertex(G,v1);j=LocateVertex(G,v2);G.arcs[i][j].adj=w;if(IncInfo)scanf("%d",&G.arcs[i][j].info);G.arcs[i][j]=G.arcs[j][i]; // 置<v1,v2>的对称弧<v2,v1>}}//CreateUDNvoid DepthFirstSearch1(MGraph G){//无向图、无向网深度优先遍历int i,j,k,visited[20],t=1,a=1; //i,j,k为计数器,visited[20]为标志符用于表示是否已经访问过SeqStack p;for(i=0;i<G.vexnum;++i) //初始化标志符visited[i]=0;visited[0]=1; //规定以第一个字符开始遍历printf("深度优先遍历开始:\n");k=0;i=0;printf("%c ",G.vertex[0]);while(i<G.vexnum){//不断以行循环在遇到符合条件时打印,每打印出一个就让t加,把合适的值用栈来表示,把指针指向新的项for(j=0;j<G.vexnum;++j){if(G.arcs[i][j].adj!=0&&G.arcs[i][j].adj!=INFINITY&&visited[j]==0){printf("%c ",G.vertex[j]);visited[j]=1;p.elem1[k]=i;p.top=k;k++;i++;a++;t++;break;}}if(j==G.vexnum){//当在某一行无法找到合适值时,输出栈内的值,返回上一行重新开始循环i=p.elem1[p.top];p.top--;k--;}if(t==G.vexnum)break; //当全部的定点都打印出来了就退出循环}printf("\n");}void BreadthFirstSearch1(MGraph G){//无向图、无向网广度优先遍历int i,j,k,visited[20],t=1; //i,j为计数器,visited[20]为标志符用于表示是否已经访问过SeqStack p;for(i=0;i<G.vexnum;++i) //初始化标志符visited[i]=0;visited[0]=1; //规定以第一个字符开始遍历printf("广度优先遍历开始:\n");k=0;i=0;printf("%c ",G.vertex[0]);while(i<G.vexnum){for(j=0;j<G.vexnum;++j)//不断以行循环在遇到符合条件时打印,每打印出一个就让t加,把指针指向新的项{if(G.arcs[i][j].adj!=0&&G.arcs[i][j].adj!=INFINITY&&visited[j]==0){printf("%c ",G.vertex[j]);visited[j]=1;p.elem1[k]=i;p.top=k;k++;t++;}}i++; //换行,重新开始循环if(t==G.vexnum)break;}printf("\n");}int CreateGraph(MGraph &G){ //构造图printf("请输入要构造的图的类型(有向图:0,有向网:1,无向图:2,无向网:3):\n");scanf ("%d",&G.kind);switch(G.kind){case 2: CreateUDG(G);break;case 3: CreateUDN(G);break;default: return ERROR;}}//CreateGraphvoid Display(MGraph G){//输出图的邻接矩阵int i,j;printf("该图的邻接矩阵为:\n");for(i=0;i<G.vexnum;++i){for(j=0;j<G.vexnum;++j){printf("%d ",G.arcs[i][j].adj);}printf("\n");}}/* main.cpp */void main(){int i;MGraph G;CreateGraph(G);DepthFirstSearch1(G);BreadthFirstSearch1(G);Display(G);scanf("%d",&i);}1、程序开始运行时输出:请输入要构造的图的类型(有向图:0,有向网:1,无向图:2,无向网:3):为了测试输入为:2显示:请输入无向图G的顶点数:输入:5显示:请输入无向图G的边数:输入:6显示:请输入无向图G的弧是否含相关信息(是:1,否:0):输入:0显示:请输入5个顶点的值(1个字符,空格隔开):输入:1 2 3 4 5显示:请输入%d条边的顶点1 顶点2(以空格作为间隔):输入:1 2 1 4 2 3 2 5 3 4 3 5显示:深度优先遍历开始:1 2 3 4 5广度优先遍历开始:1 2 4 3 5该图的邻接矩阵为:0 1 0 1 01 0 1 0 10 1 0 1 11 0 1 0 00 1 1 0 0请输入任意键退出2、程序运行结果如图:。