数据结构-王道2017-第5章 图

1.图的基本概念

  1)图的定义

     图G由顶点集V和边集E组成,记为G=(V,E),其中V(G)表示图G中定点的有限非空集;E(G)表示图G中顶点之间的关系(边)集合。V={v1,v2,..,vn},用|V|表示图G中顶点的个数,也称为图G的阶,E={(u,v)| u ∈ V,v ∈ V},用|E|表示图G中边的条数。

   注意:线性表可以是空表,树可以是空树,但图不可一世空图。就是说图中不能一个顶点也没有,图的顶点集一定非空,但边集E可以为空,此时图中只有顶点没有边

   2)简单图:不存在重复边;不存在顶点到自身的边,则称图G为简单图

        多重图:图G中两个结点之间的边数多于一条,又允许顶点通过同一条边与自己关联,则G为多重图。多重图的定义和简单图是相对的。

       完全图:在无向图中,如果任意两个顶点之间都存在边,则称该图为无向完全图,含有n个顶点的无向完全图又n(n-1)/2条边,含有n个顶点的有向完全图有n(n-1)条有向边

   3)连通:在无向图中,若从顶点v到顶点w有路径存在,则称v和w是连通的,若图G中任意两个顶点都是连通的,则称图G为连通图,否则称为非连通图

       无向图中的极大连通子图称为连通分量,如果一个图有n个顶点,并且有小于n-1条边,那么此图必是非连通图。

  注意:极大连通子图要求该连通子图包含其所有的边;极小连通子图是既要保持图连通,又要使得边数最少的子图。

  4)强连通图、强连通分量

     在有向图中,若从顶点v到顶点w和从顶点w到顶点v之间都有路径,则称这两个顶点是强连通的。若图中任何一对顶点都是强连通的,则称该图为强连通图。有向图的极大强连通子图称为有向图的强连通分量。

  5)生成树、生成森林

      连通图的生成树是包含图中全部顶点的一个极小连通子图。如果图中定点数为n,则它的生成树含有n-1条边。对于生成树而言,看去他的一条边,则会变成非连通图,若加上一条边则会形成回路。在非连通图中,连通分量的生成树构成了非连通图的生成森林。

    注意:包含无向图中全部顶点的极小连通子图,只有生成树满足条件,因为砍去生成树的任意一条边,图将不再连通。

  6)定点的度、入度出度

      每个顶点的度定义为以该顶点为一个端点的边的数目

      对于无向图,顶点v的度是指依附于该顶点的边的条数,记为TD(v);无向图的全部顶点的度之和等于边数的两倍,这是因为每条边和两个顶点相关联。

      对于有向图,顶点v的度分为入度和出度,入度是以顶点v为终点的有向边的数目,记为ID(v),出度是以顶点v为起点的有向边的数目,记为OD(v),顶点v的度等于出度和入度之和TD(v) = ID(v) +OD(v);

     有向图的出度和入度之和相等并且等于边数。

   7)边的权和网

     在一个图中,每条边都可以标上具有某种含义的值,该数值称为该边的权值。这种边上带权值的图称为带权图,也称为

   8)稠密图、稀疏图

   边数很少的图称为稀疏图,反之,称之为稠密图。一般当图满足|E|<|V|*log|V|时,可以看做稀疏图

   9)路径、路径长度和回路

     顶点v1到v2的一条路径指的是顶点序列,路径上边的数目称为路径长度。第一个顶点和最后一个顶点相同的路径称为环或回路。如果一个图有n个顶点,并且有大于n-1条边,这个图一定有环。

   10)简单路径、简单回路

  在路径序列中,顶点不重复出现的路径称为简单路径、除了第一个和最后一个顶点之外,其余顶点不重复出现的回路称为简单回路。

   11)距离

  从顶点u出发到顶点v的最短路径若存在,则此路径的长度称作从u到v的距离。若从u到v根本不存在路径,则记该距离为无穷.

   12)有向树:有一个顶点的入度为0,其余顶点的入度均为1的有向图称为有向树。

     

2.图的存储及基本操作

  所选存储方式应该适合于欲求解的问题,无论是无向图还是有向图,主要的存储方式都有两种:邻接矩阵和邻接表。前者属于图的顺序存储结构,后者属于图的链接存储结构。

   1)邻接矩阵法  

     稠密图适合使用邻接矩阵的存储表示

   2)邻接表法

     当图为稀疏图时,使用邻接矩阵会浪费大量的空间。而图的邻接表法结合了顺序存储和链式存储方法,大大减少了这种不必要的浪费。

     对图G中的每个顶点vi建立一个单链表,第i个单链表中的结点表示依附于顶点vi的边(对于有向图则是以顶点vi为尾的弧),这单链表称为vi的边表(对于有向图,则称为出边表),在邻接表中,存在两种结点:顶点表结点和边表结点。

#define MaxVertexNum 100typedef struct ArcNode{int adjvex;            //弧指向的邻接点的位置---顶点数组下标struct ArcNode * next;  //指向下一条边的指针//ElemType data;      //网的边权值
}ArcNode;typedef struct VNode{VertexType data;          //顶点信息ArcNode * first;            //指向边表第一个结点
}VNode,AdjList[MaxVertexNum];    typedef struct {AdjList vertices;    //邻接表int vexnum,arcnum;  //图的顶点数和弧数
}ALGraph;             //ALGraph是以邻接表存储的图类型

   a)邻接表特点

      如果G为无向图,则所需存储空间为O(|V|+2|E|);如果G为有向图,则所需的存储空间为O(|V|+|E|),无向图中,每条边会出现两次

      邻接表中,给定一个顶点很容易查到它的所有邻边,在邻接矩阵中需要扫描一行,时间为O(n),如果要确定给定的两个顶点间是否存在边,则在邻接矩阵中可以立即查到,在邻接表中则需要在相应结点中查找另一结点,效率较低。

  3)十字链表

      十字链表是有向图的一种链式存储结构,在十字链表中,对应于每条弧有一个结点,对应于每个顶点也有一个结点。

    

#define MaxV 100
//本质上也是邻接表
typedef struct ArcNode{              //边表结点int tailVex,headVex;                //弧的头尾结点struct ArcNode * hlink,*tlink;   //分别指向弧头相同和弧尾相同的结点
//   ElemType data;                       //相关信息
}ArcNode;typedef struct VNode{VertexType data;                 //顶点信息ArcNode *firstin,*firstout;   //指向第一条入弧和出弧
}VNode;           typedef struct{  VNode xList[MaxV];      //十字链表int vexnum,arcnum;   //图的顶点数和边数
}GLGraph;                    //以十字链表存储的图类型

在十字链表中,极容易找到vi为尾的弧,也容易找到以vi为头的弧,因而容易求出顶点的出度和入度。

 图的十字链表是不唯一的,但一个十字链表表示确定一个图。

4)邻接多重表

   邻接多重表是无向图的另一种链式存储结构,与十字链表类似,每一条边用一个结点表示

          mark | ivex | ilink | jvex | jlink | info

   mark 为标志域,标记该条边是否被搜索过;ivex和jvex分别表示该边依附的两个顶点,ilink指向下一条依附于ivex的边,jlink指向下一条依附于顶点jvex的边,info为指向和边相关的各种信息的指针域。

 每一个顶点也用一个结点表示,由如下所示的两个域组成

   data | firstedge

 每一条边只有一个结点

#define MaxVertexNum 100
typedef struct ArcNode{bool mark;                              //访问标记int ivex,jvex;                          //分别指向该弧的两个结点struct ArcNode *ilink,*jlink;  //分别指向两个顶点的下一条边//InfoType info;   //相关信息
}ArcNode;typedef struct VNode{     //顶点表结点VertexType data;          //顶点信息ArcNode * firstedge;     //指向第一条依附在该顶点的边
}VNode;typedef struct{VNode adjmuList[MaxVertexNum];   //邻接表int vexnum,arcnum;                  //图的顶点数和弧数
}AMLGraph; 

3.图的遍历

   图的遍历是指从图中的某一顶点出发,按照某种搜索方法沿着图中的边对图中的顶点访问一次且仅访问一次。注意到树是一种特殊的图,所以树的遍历也可以看做是一种特殊的图的遍历。两种算法:广度优先搜索和深度优先搜索。

   1)  广度优先搜索(Breadth-First-Search,BFS)

     类似于二叉树的层序遍历算法

 

#define MAX_N 100
bool visited[MAX_N];void BFSTraverse(Graph G,){for(int i = 0;i < G.vnum;i++)visited[i] = false;InitQueue(Q);for(int i = 0;i < G.vnum;i++)if(!visited[i])BFS(G,i);
}void BFS(Graph G, int v){visit(v);visited[v] = true;EnQueue(Q,v);while(!Empty(Q)){DeQueue(Q,v);       //顶点v出列for(w=neighbor(G,v);w>=0;w=nextNeighbor(G,v,w)){
if(!visited[w]){
          visit(w);visited[w] = true;EnQueue(Q,w);

}
      }}}

  性能分析:无论是邻接表还是邻接矩阵的存储方式,BFS算法都需要借助一个辅助队列Q,n个顶点都需入队一次,在最坏的情况下,空间复杂度为O(|V|)

   采用邻接表存储时,每个顶点均需搜索一次(或入队一次),故时间复杂度为O(|V|),在搜索任一顶点的邻接点时,每条边至少访问一次,故时间复杂度为O(|E|),算法总的时间复杂度为O(|V|+|E|).当采用邻接表存储时,查找每个顶点的邻接点所需时间为O(|V|),故算法总的时间复杂度为O(|V|^2)。

  可以使用BFS算法求解单源最短路径。

   给定图的邻接矩阵存储表示是唯一的,故其广度优先生成树也是唯一的,但由于邻接表存储表示不唯一,故其广度优先生成树也是不唯一的。

  2)深度优先搜索

    类似于树的先序遍历

    

#define MAX_N 100
bool visited[MAX_N];void DFSTraverse(Graph G){for(int i = 0;i < G.vnum;i++){visited[i] = false;}for(int i =0;i < G.vnum;i++){  //对于每个连通分量进行遍历if(!visited[i])DFS(G,i);              }
}void DFS(Graph G, int v){visit(v);visited[v] = true;         //已经访问for(w=neighbor(G,v);w >= 0;w=nextneighbor(G,v,w)){if(!visited[w])      //尚未访问结点
              DFS(G,w);}
}

 注意:同一个图基于邻接矩阵的遍历所得到的DFS序列和BFS序列是唯一的,基于邻接表的遍历所得到的bfs和dfs是不唯一的(因为邻接矩阵唯一,而邻接表表示不唯一)

DFS算法的性能分析:

   是一个递归算法,需要借助递归工作栈,空间复杂度为O(|V|);遍历图的过程实质上是对每个顶点查找其邻接点的过程,其耗费的时间取决于采用的存储结构。以邻接矩阵表示,查找每个顶点的邻接点的所需时间为O(|V|),故总的时间复杂度为O(|V|^2).以邻接表表示时,查找所有顶点的邻接点所需时间为O(|E|),访问顶点所需时间为O(|V|),总的时间复杂度为O(|V|+|E|);

 

    

 

转载于:https://www.cnblogs.com/--CYH--/p/6790242.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/488457.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python两个参数or循环_python学习笔记(四)、条件、循环及其他语句

1 再谈print和import1.1 打印多个参数print 能够同时打印多个表达式&#xff0c;并且能自定义分隔符。如下&#xff1a;print(a,b,c)  ——> a b cprint(a,b,c,sep"_")  ——> a_b_c1.2 import导入模块时&#xff0c;能够给导入的模块取一个别名(相对于生活…

研究揭示大脑在工作记忆中存储信息的神经机制

来源&#xff1a;中国科学院脑科学与智能技术卓越创新中心&#xff08;神经科学研究所&#xff09;3月5日&#xff0c;《神经元》期刊在线发表了题为《无颗粒岛叶皮层瞬时性神经元活动调控学习新任务时的工作记忆存储》的研究论文。该研究由中国科学院脑科学与智能技术卓越创新…

[Jmeter] 基本使用的总结

转载于:https://www.cnblogs.com/mytianying/p/6793461.html

java 仿qq登录界面7.1_安卓开发学习笔记(七):仿写腾讯QQ登录注册界面

这段代码的关键主要是在我们的相对布局以及线性布局上面&#xff0c;我们首先在总体布局里设置为线性布局&#xff0c;然后再在里面设置为相对布局&#xff0c;这是一个十分常见的XML布局模式。废话不多说&#xff0c;直接上代码&#xff1a;一.activity.xml>android:layout…

python numpy.array_python的numpy.array

为什么要用numpyPython中提供了list容器&#xff0c;可以当作数组使用。但列表中的元素可以是任何对象&#xff0c;因此列表中保存的是对象的指针&#xff0c;这样一来&#xff0c;为了保存一个简单的列表[1,2,3]。就需要三个指针和三个整数对象。对于数值运算来说&#xff0c;…

【前沿科技】云计算军事运用有啥特点

来源&#xff1a; 军语开源情报研究所云计算技术被视为继大型计算机、个人计算机、互联网之后的第四次信息技术产业革命。云计算是一种围绕分布式共享计算资源的创新应用模式&#xff0c;资源提供者可以方便而快速地提供计算资源&#xff0c;而无处不在的资源需求者可以便利地使…

tools URL 收集

每次恢复快照都会把CHrome的标签弄没&#xff0c;所以将收藏的好资源放在这里以免又丢了。 IP 段查询下载&#xff0c;做黑白名单用的到 http://ipblock.chacuo.net/ 转载于:https://www.cnblogs.com/M4ster/p/tools_url.html

python 通过ip获取城市_python 根据ip获取地理位置

!/usr/bin/pythoncodingutf-8import dpktimport socketimport pygeoipimport optparsegi pygeoip.GeoIP(GeoLiteCity.dat)查询数据库相关的城市信息并输出def printRecord(tgt):rec gi.record_by_name(tgt)city rec[city]# 原来的代码为 region rec[region_name]&#xff0…

js原型和原型链_JS 构造函数与原型链

JavaScript 对象体系是基于构造函数和原型链的。继承不通过类&#xff0c;而是通过原型对象实现&#xff0c;原型对象的所有属性和方法&#xff0c;都能被实例对象共享。构造函数&#xff08;constructor&#xff09;在 JS 中想要生成可重用、可继承的对象就要使用构造函数&…

全球制造业的未来

来源&#xff1a;航空简报2020年3月4日&#xff0c;Brahima Coulibaly和Karim Foda在美国布鲁金斯学会官网刊文&#xff0c;分析了全球制造业的未来&#xff0c;提出了几个鲜明的观点&#xff1a;1.“比较优势”将发生转移&#xff0c;中等收入国家尤其是许多亚洲新兴经济体&am…

关于解决织梦文档栏目删除后ID 从1开始的方法

在织梦当删除文档栏目后&#xff0c;再重新建立文档时&#xff0c;它的id就会按照刚才建立的文档的id的数值再增加一个&#xff0c; 比如&#xff0c;开始建立的文档id是1&#xff0c;当删除后&#xff0c;要重新再建立一个文档时&#xff0c;文档的后面的id已经不是从1开始&am…

mybatis 批量修改_解放双手,不写SQL!一个开源 MyBatis 神器!!

什么是通用 Mapper&#xff1f;它是一个可以方便的使用 Mybatis 进行单表的增删改查优秀开源产品。它使用拦截器来实现具体的执行 Sql&#xff0c;完全使用原生的 Mybatis 进行操作。在 Github 上标星 9.6K&#xff01;为什么要用 Mapper&#xff1f;它提供了所有单表的基本增删…

论文速读:AI能从人类的愚蠢中学到什么?

来源&#xff1a;混沌巡洋舰本文来自对下面论文的编译和解读&#xff1a;导读&#xff1a;随着机器在某些认知问题上超越人类&#xff0c;人机协作将会带来越来越显著的影响。造成人类偏见的三个主要原因&#xff08;小而不完整的数据集&#xff0c;从自己的决策结果中学习&…

struts2的核心和工作原理

在学习struts2之前&#xff0c;首先我们要明确使用struts2的目的是什么&#xff1f;它能给我们带来什么样的优点&#xff1f; 设计目标 Struts设计的第一目标就是使MVC模式应用于web程序设计。在这儿MVC模式的优点就不在提了。技术优势 Struts2有双方面的技术优势&#xff0c;一…

python函数递归法求一个数各位数之和_python – 设计一个使用digit_sum计算数字总和的递归函数...

要获得(正整数)数字的最后一位数,您可以计算模数&#xff1a;last_digit n % 10该数字的其余部分(不包括最后一个地方)是&#xff1a;rest (n - last_digit) / 10理论上这应该足以分割数字并添加数字&#xff1a;def sum_digits(n):if n < 10:return nelse:last_digit n …

mysql允许root远程连接_西部数码使用指南:远程桌面之终端服务器超出了最大允许连接数解决...

版权归西部数码所有&#xff0c;原文链接&#xff1a;https://www.west.cn/faq/list.asp?unid739出现这种情况的原因和解决办法。 原因:用远程桌面链接登录到终端服务器时经常会遇到“终端服务器超出最大允许链接数”诸如此类错误导致无法正常登录终端服务器&#xff0c;引起该…

关于征集2020重大科学问题和工程技术难题的通知

来源&#xff1a;中国指挥与控制学会学会全体会员&#xff1a;为研判未来科技发展趋势、前瞻谋划和布局前沿科技领域与方向&#xff0c;瞄准世界科技前沿&#xff0c;推进世界科技强国建设&#xff0c;根据《中国科协办公厅关于征集2020重大科学问题和工程技术难题的通知》精神…

java hive配置_Hive配置项的含义详解(1)

一个hive任务&#xff0c;如何才算是优化的任务&#xff0c;hadoop job config里哪些配置能影响hive的效率。看看hive的详细配置我们可以略知一二。hive的配置&#xff1a;hive.ddl.output.format&#xff1a;hive的ddl语句的输出格式&#xff0c;默认是text&#xff0c;纯文本…

怎么在别人网站注入js脚本_别人的网站是怎么实现引流的?这些站外SEO技巧是关键...

点击上方蓝字关注我们&#xff01;因为分享&#xff0c;我们相遇在SEO路上“网站上线一段时间了&#xff0c;为什么没有流量&#xff1f;为什么没有询盘&#xff1f;”对于做网络营销的企业而言&#xff0c;网站流量与询盘是建立网站的根本目的&#xff0c;可是为什么操作了一段…

比尔盖茨NEJM发文:新冠肺炎是百年一遇的流行病!全世界应该如何应对?

来源&#xff1a;生物谷面对任何危机&#xff0c;政府都有两个同等重要的责任&#xff1a;解决眼前的问题&#xff0c;并防止它再次发生。COVID-19大流行就是一个恰当的例子。我们现在需要拯救生命&#xff0c;同时也需要改善我们应对疫情的方式。第一点更为紧迫&#xff0c;但…