您的位置:首页 > 理论基础 > 数据结构算法

大话数据结构5 - 图

2017-02-10 18:44 176 查看
线性结构:一对一
树形结构:一对多
图形结构:多对多

图:顶点的(有穷非空)集合、顶点之间边的集合
G(V,E),G图,V顶点,E边
注意:
1、数据元素:线性->元素,树->结点,图->顶点vertex
2、空表,空树,但是没有空图:顶点集不能为空,边集可以是空的

一:图graph,简单图
1、无向边,无序偶对(vi,vj)=(vj,vi)
无向图:顶点n,边e、0≦e≦n*(n-1)/2
无向完全图:n,e=n*(n-1)/2
2、有向边、弧,有序偶<vi,vj>、vi弧尾、vj弧头,≠<vj,vi>
有向图:顶点n,边e、0≦e≦n*(n-1)
有向完全图:n,e=n*(n-1)
3、稀疏图,稠密图
4、网network,权weight:顶点到顶点的距离或耗费
5、子图

二:顶点与边的关系,G=( V,{E} )
1、邻接点,相关联,度
无向图:顶点v、v'互为邻接点,边与顶点相关联,顶点v的度TD(v),边


有向图:顶点v邻接到顶点v'、顶点v'邻接自顶点v,弧与顶点相关联,顶点v的度TD(v)=ID(v)+OD(v)、入度InDegree、出度OutDegree,边


2、路径、顶点序列,路径长度,简单路径
有向图,路径也是有向的

注意:树中根到任意结点的路径是唯一的,图中顶点与顶点的路径是不唯一的
3、回路、环,简单回路、简单环

三:连通图
注意:有路径就是连通,来回都有路径就是(强)连通图
1、无向图:顶点v、v'有路径、v与v'连通,连通图,连通分量:极大连通子图
连通图的生成树:极小连通子图,顶点n、边n-1
注意:有n个顶点、n-1条边的不一定是生成树
注意:一个图有n个顶点,1.小于n-1条边,则是非连通图,2.多于n-1条边,则是一个环
2、有向图:顶点v到v',v'到v都有路径,强连通图,强连通分量:极大强连通子图
有向树,生成森林
注意:有向树、生成森林都不是强连通图

四:图的抽象数据类型

五:图的存储结构,G=( V,{E} ),顶点n、边e
不适合:简单顺序存储、多重链表
1、邻接矩阵,数组+数组,边表/集是数组,重要
一维数组存储顶点,二维数组(邻接矩阵)存储边/弧
顶点数组vertex
,边/弧数组arc

、n*n的方阵
无向图:边数组是对称矩阵、aij=aji,顶点vi的度=边数组第i行元素之和
有向图:弧数组不对称,顶点的入度=列元素之和、出度=行元素之和
网:有边/弧=wij(权值),对角线=0,无边/弧=∞(极限值)
无向网图,有向网图
适用:稠密图,读存数据较多、结构修改较少的图
缺点:如果是稀疏图就会造成空间浪费
2、邻接表,数组+单链表,边表/集是链表,重要
一维数组存顶点,单链表存邻接点(构成的线性表)的下标
顶点表,边表、出边表:以顶点为弧尾来存储
逆邻接表,入边表:以顶点为弧头的表
适用:稀疏图,读存数据较少、结构修改较多的图
缺点:对于有向图,有了出边表就没有入边表,有了入边表就没有出边表


 


3、十字链表,数组+多重链表,邻接表+逆邻接表,有向图邻接表的优化存储结构
用于有向图的应用





4、邻接多重表,数组+多重链表,无向图邻接表的优化存储结构
用于无向图的应用

5、边集数组,数组+数组,考虑的是对边的关注
一维数组存储顶点,一维数组存储边/弧
顶点数组
,边/弧数组[e]、e(begin,end,weight)
适合对边依次进行处理的操作

六:图的遍历
同树的遍历类似:次序、访问、所有顶点、有且仅有一次被访问
访问数组:有了访问数组,就可以确定该顶点是否被访问过,避免顶点重复被访问,需要注意的是,当碰到重复的顶点时,该顶点已经被标记过了,就不会被访问,而是再返回原路径继续查找没有被访问过的顶点。
注意:遍历中强调,所有顶点有且仅有一次被访问,指的是顶点信息只能被访问一次,而不是指到达顶点的路径只可以走一次,所以路径是可以重复
1、深度优先遍历:DFS,depth first search,深度优先搜索,递归,类似树的前序遍历
2、广度优先遍历:BFS,breadth first search,广度优先搜索,类似树的层序遍历
对于非连通图,对它的连通分量进行遍历
注意:1和2仅仅在于对顶点的访问顺序不同,选择哪种遍历算法,要看遍历的目的

七:图的应用及算法
注意:1和2都是有环图的应用,无向、有向都可以;3和4是有向无环图(即图中没有回路)的应用,也是工程问题上的应用
注意:树结构中,根结点到任意结点的路径唯一,生成树也是树结构
注意:环结构中,从一个顶点到另一个顶点的路径不唯一,即有两条及以上的路径可以选

1、最小生成树,无向有环图:连通网的最小代价生成树
注意:这里仅讨论了无向图的最小生成树;有向图的最小生成树,称为最小树形图,这里并为讲解/涉及
网结构,顶点n,边n-1,连通图,生成树,极小连通子图
注意:生成树要求包括所有顶点n个和保留n-1条边
①普里姆(Prim)算法:以某顶点为起点,逐步找各顶点上最小权值的边来构建最小生成树,走一步看一步,使用邻接矩阵结构
算法:一维数组adjvex[顶点数]、lowcost[顶点数]
注意:此算法适用稠密图,即边非常多的情况
②克鲁斯卡尔(Kruskal)算法:以边为目的去构建最小生成树(注意要考虑是否会形成环路),即从最短边开始,逐步在剩下的边中选择一条不会产生环路的具有最小权值的边来构建最小生成树,从全局入手,使用边集数组结构
算法:一维数组parent[顶点数]
注意:此算法适用稀疏图,即边数少的情况

2、最短路径,有环图,路径选择
注意:无向图、有向图都可以求最短路径
源点,终点
非网图:边数最少
网图:权值之和最少
①迪杰斯特拉(Dijkstra)算法:按路径长度递增的次序产生最短路径的算法,换句话说是,基于已经求出的最短路径的基础上,求得更远顶点的最短路径,使用邻接矩阵结构
算法:一维数组P[顶点数]:路径、D[顶点数]:最小权值和
注意:此算法是,从某个源点到其余各顶点的最短路径问题
注意:在最外添加一层循环,可以变成所有顶点到所有顶点的最短路径问题
②弗洛伊德(Floyd)算法:使用邻接矩阵结构,n是顶点数
二维数组D

:最短路径权值和矩阵,初始化:网图的邻接矩阵
二维数组P

:前驱矩阵、存储路径,初始化:P[i][j]=j

D0[v][w]=min{D-1[v][w],D-1[v][0]+D-1[0][w]}
[align=left]Dk[v][w]=min{Dk-1[v][w],Dk-1[v][k]+Dk-1[k][w]},中转顶点k(0≦k≦n-1)[/align]

注意:此算法是,所有顶点到所有顶点的最短路径问题

3、拓扑排序,有向无环图,主要是解决一个工程是否能顺利进行的问题
㈠概念:
a.项目工程、活动、子工程:所有的活动组成一个工程,其中若干个活动组成一个子工程
b.AOV网:actiivity on vertex network,一个表示工程的有向图中,顶点表示活动,弧表示优先关系,这种有向图的顶点表示活动的网,称为AOV网,AOV网是表示工程流程,用来对工程建模的
AOV网的工程特性:只有在进入某顶点的各项活动都已经结束,该顶点表示的活动才可以开始
注意:AOV网不能存在回路,即这样的工程图是无环的有向图
c.拓扑序列:有向图的顶点序列,满足从vi到vj有一条路径,在顶点序列中vi在vj前面
注意:拓扑序列不唯一
拓扑排序:对一个有向图构造拓扑序列的过程
注意:构造时,如果所有顶点都在序列中,说明该有向图不存在环/回路,是AOV网;如果哪怕少了一个顶点,说明该有向图有环/回路,不是AOV网
㈡算法:研究AOV网的拓扑排序更有价值,可以用在工程、项目流程图
使用邻接表结构,增加入度域in、栈结构stack、以空间换时间
注意:malloc函数、sizeof函数,入栈stack[++top]=i,出栈gettop=stack[top--]

4、关键路径,有向无环图,主要是解决工程完成需要的最短时间问题
㈠概念:
a.AOE网:actiivity on edge network,一个表示工程的带权有向图中,顶点表示事件,弧表示活动,弧上的权值表示活动的持续时间,这种有向图的弧表示活动的网,称为AOE网,AOE网也是表示工程流程的,用来对工程建模的
AOE网的工程特性:在某顶点表示的事件发生后,从该顶点出发的各项活动才能开始,只有在进入某顶点的各项活动都已经结束,该顶点表示的事件才能发生
始点/源点,终点/汇点
注意:一般情况下,AOE网只有一个源点一个汇点,但也可以有多个,那就是复杂流程图了
AOV网和AOE网的不同:AOV网是顶点表示活动的网,只描述活动之间的制约关系问题;AOE网是弧表示活动、弧权值表示活动持续时间的网,是建立在活动之间制约关系没有矛盾的基础之上,再来分析完成整个工程至少需要的时间,或者为缩短完成工程所需时间,应当加快哪些活动等问题
b.关键路径:一条路径的权值和,称为路径长度;从源点到汇点路径长度最大的路径,称为关键路径;关键路径上的活动,称为关键活动
注意:反过来,关键活动组成的路径就是关键路径
注意:关键路径可以有唯一条,也可以有多条,如果有多条关键路径,那么必须同时缩短这几条关键路径的路径长度,即提高路径上的活动的速度,才可以达到缩短工期的目的
注意:多条关键路径上的关键活动可能是存在重复,也可能不存在重复
㈡算法:
原理:活动的最早开始时间=最晚开始时间,该活动就是关键活动
使用邻接表结构,栈结构stack2,n是顶点数,k(0≦k≦n-1)
事件最早和最晚发生时间etv、ltv(一维数组),活动最早和最晚开始时间ete、lte(变量)

[align=justify]事件最早发生时间,事件k的etv:[/align]



P[K]表示所有到达顶点Vk的弧的集合,len<vi,vk>表示弧<vi,vk>的权值。
[align=justify]事件最晚发生时间,事件k的ltv:[/align]



P[K]表示所有从顶点Vk出发的弧的集合,len<vk,vj>表示弧<vk,vj>的权值。

[align=left]活动最早开始时间,活动<vi,vj>的ete:ete=etv[i][/align]

活动最晚开始时间,活动<vi,vj>的lte:lte=ltv[j]-len<vi,vj>
算法步骤:

①从源点到汇点求拓扑排序,一边将排序的顶点序号压入栈stack2,一边求etv
②初始化ltv[i]=etv[n-1],n是顶点数
③拓扑排序反过来进行,即从汇点到源点,逆序输出拓扑排序的顶点序号,一边将栈stack2中的序号出栈(逆序),一边求ltv
④遍历每个顶点及其弧表,求ete、lte、关键活动,并输出弧
⑤最后打印出的路径,就是关键路径
注意:最后求的不是表示事件的顶点,而是最短时间,是弧组成的路径,即关键活动组成的关键路径
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  数据结构