线性表可以是空表,树可以是空树,但图不可以是空图
无论是有向图还是无向图,主要的存储方式都有两种:邻接矩阵和邻接表。前者图的数据顺序存储结构,后者属于图的链接存储结构。
所谓邻接矩阵存储,就是用一个一维数组存储图中顶点的信息,用一个二维数组存储图中边的信息(即各顶点之间的邻接关系)。
十字链表是有向图的一种链式存储结构。
图的十字链表表示是不唯一的,但一个十字链表表示确定一个图。
邻接多重表是无向图的另一种链式存储结构。
图的遍历是指从图中的某一顶点出发,按照某种搜索方法沿着图中的边对图中的所有顶点访问一次且仅访问一次。
图的遍历主要分为两种算法:广度优先搜索和深度优先搜索
为了实现逐层的访问,算法必须借助一个辅助队列,以记忆正在访问的顶点的下一层顶点。
假设从a结点开始访问,a先入队,此时队列非空,取出队头元素a,由于b、c与a邻接且未被访问过,于是依次访问b、c,并将b、c依次入队。队列非空,取出队头元素b,依次访问与b邻接且未被访问的顶点d、e,并将d、e入队(注意: a与b也邻接,但a已置访问标记,故不再重复访问)。此时队列非空,取出队头元素c,访问与c邻接且未被访问的顶点f、g,并将f、g入队。此时,取出队头元素d,但与d邻接且未被访问的顶点为空,故而不进行任何操作。继续取出队头元素e,将h入队列....当最后取出队头元素h后,队列为空,从而循环自动跳出。遍历结果为abcdefgh。
BFS算法都需要借助一个辅助队列Q,n个顶点均需入队一次,在最坏的情况下(一个横排),空间复杂度为O(|V|)
O(|V|)
,故算法总的时间复杂度为O(|V|²)
。O(|V|)
,在搜索任一顶点的邻接点时,每条边至少访问一次,故时间复杂度为O(|E|)
,算法的总时间复杂度为O(|V|+|E|)
。在广度遍历的过程中(有向图&无向图),我们可以得到一颗遍历树,称为广度优先生成树。需要注意的是,一给定图的邻接矩阵存储表示是唯一的,故其广度优先生成树也是唯一的,但由于邻接表存储表示不唯一,故其广度优先生成树也是不唯一的。
深度优先搜索(DFS)类似于树的先序遍历。
首先访问a,并置a已访间标记;然后访问与a邻接且未被访问的顶点b,置b已访问标记;然后访问与b邻接且未被访问的顶点d,置d已访问标记。此时d已没有未被访问过的邻接点,故返回上一个访问过的顶点b,访问与其邻接且未被访问的顶点e,置e访问标......依次类推,直到图中所有的顶点访问-次且仅访问次。遍历结 果为abdehcfe。
DFS算法是一个递归算法,需要借助一个递归工作栈,最坏情况下(一个竖排),它的空间复杂度为O(|V|)
。
O(|V|)
,故算法总的时间复杂度为O(|V|²)
。O(|E|)
,访问顶点所需要时间为O(|V|)
,此时,算法的总时间复杂度为O(|V|+|E|)
。对于连通图调用DFS才可以产生深度优先生成树(有向图&无向图),否则产生的将是深度优先生成森林。和BFS类似,基于邻接表存储产生的深度优先生成树是不唯一的。
对于同一个图,基于邻接矩阵的遍历所得到的DFS序列和BFS序列是唯一的,基于邻接表的遍历所得到的DFS序列和BFS序列是不唯一的。
图的应用主要包括:最小生成(代价)树、最短路径、拓扑排序和关键路径。
一个连通图的生成树是图的极小连通子图,它包含图中的所有顶点,并且只含尽可能少的边。这意味着对于生成树来说,若砍去它的一条边,就会使生成树变成非连通图若给它增加一条边,就会形成图中的一条回路。
假设G=(V, E)是一个带权连通无向图,U是顶点集V的一个空子集。
Prim算法的时间复杂度为O(|V|²)
,不依赖|E|,因此它适用于求解边稠密的图的最小生成树。
与普里姆算法从顶点开始扩展最小生成树不同,克鲁斯卡尔算法是一种按照权值的递增次序选择合适的边来构造最小生成树的方法。
通常在克鲁斯卡尔算法中,采用堆来存放边的集合,则每次选择最小权值的边只需要O(log₂|E|)
的时间。又生成树T中所有边可以看做一个等价类,每次添加新的边的过程类似于求解等价类的过程,由此可以采用并查集的数据结构来描述T,从而构造T的时间复杂度为O(|E|log₂|E|)
,因此克鲁斯卡尔算法适合边稀疏而顶点多的图。
带权有向图G的最短路径问题,一般可分为两类:一是单源最短路径,即求图中某一个顶点到其他顶点的最短路径,可通过经典的Dijkstra算法求解;二是求每一对顶点间的最短路径,可通过Floyd-Warshall算法求解。
求带权有向图中某个源点到其余各顶点的最短路径,最常用的是Dijkstra算法。`如下图,从顶点1开始出发,求其到其余顶点的最短路径。
若使用邻接矩阵表示,它的时间复杂度为O(|V|²)
;若使用邻接表表示,其时间复杂度仍为O(|V|²)
如果边上带有负权值,Dijkstra算法不适用
Floyd算法时间复杂度O(|V|³)
弗洛伊德允许图中带负权值的边,但不允许有包含负权值的边组成的回路。弗洛伊德算法同样也适用与带权无向边
带权有向图中,以顶点表示事件,有向边表示活动,边上的权值表示完成该活动的开销,则称这种有向图为用边表示活动的网络,简称为AOE
网。
在AOE
网中仅有一个入度为0的顶点,称为开始顶点(源点),它表示整个工程的开始;网中也仅存在一个出度为0的顶点,称为结束顶点(汇点),它表示整个工程的结束。从源点到汇点的所有路径中,具有最大路径长度的路径称为关键路径。把关键路径上的活动称为关键活动。
对于关键路径,注意以下几点:
有向无环图:一个有向图中不存在环,则称为有向无环图,简称DAG
图。
拓扑排序:在图论中,由一个有向无环图的顶点组成的序列,当且仅当满足以下条件时,称为该图的一个拓扑排序。
或者定义为:拓扑排序是对有向无环图的顶点的一种排序,它使得如果存在一条从顶点A到顶点B的路径,那么在排序中顶点B出现在顶点A后面。每个DAG图都是一个或多个拓扑排序序列。
DAG图进行拓扑排序的算法:
DAG
图中选择一个没有前驱的顶点并输出DAG
图为空或当前图中不存在无前驱的顶点为止拓扑排序的时间复杂度为O(|V|+|E|)
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。