图的应用基础
一、图的类型
名称 | 特征 |
无向图 | 边没有方向 |
有向图 | 边有方向 |
加权无向图 | 边有权值但没有方向 |
加权有向图 | 边有权值且有方向 |
二、图的表示:G = (V, E)
1、邻接表
对V的每个顶点都用一个表来表示,每个表中包含所有与该顶点相邻的顶点组成,所有的表构成图的邻接表。
具体实现形式:每个表中的数据格式可为:顶点编号、顶点的度、依次列出与该顶点相邻的顶点编号。可用vector类型的数组来表示: vector<int> G[n]。
2、邻接矩阵
用|V|*|V|的矩阵来表示,顶点i到顶点j存在边则aij为1
三、图的搜索算法
1、深度优先搜索
以“能走多远就走多远”为基本规则。对顶点v的边进行递归搜索,当v的边全部搜索完毕后,则回归并继续搜索前一顶点。
需要对各顶点记录两个时间节点:d[v], 记录第一次访问v的时刻;f[v], 记录调查完v的邻接表的时刻。
实现过程及其变量:
1. 从最初访问的顶点0开始,将其压入栈中(Stack S) 2. 只要栈中仍然有顶点,就循环下述操作 访问栈顶部的顶点u; 从当前访问的顶点u移动至与其相邻的顶点v时,将v压入栈中。若当前顶点u不存在未访 问的相邻顶点,则将u从栈中删除; 3. 若仍有顶点未被发现,则选择其中编号最小的作为新的起点继续搜索。
用枚举类型来标记各个顶点的访问状态(未访问、当前被访问、访问过的点、访问结束的点)
邻接矩阵
栈,用于暂存访问过程中的顶点
2、广度优先搜索
尽可能地搜索与已搜索顶点相邻的未搜索顶点,再以此类推不断扩大搜索范围。可用作求最短路径的一个算法。
会记录各顶点v到起点s的距离d[v]
实现过程及其变量:
1. 将起点s放入队列Q中 2. 只要Q不为空,则循环执行下述处理 从Q中取出顶点u进行访问(访问结束); 将与u相邻的未访问顶点v放入Q中,并将d[v]更新为d[u]+1 ; 标记顶点状态:未访问、当前访问、队列中的顶点、访问结束。 邻接矩阵 队列Q 最短距离数组d[n]
四、加权图
1、基本概念
最小生成树:利用图生成的树中,各边权值总和最小;
最短路径问题:求出给定两顶点之间各边权值总和最小的路径;
最短路径生成树:在各边非负的加权图中,若顶点s到G的所有顶点都存在路径,则一定存在一棵以s为根,且s到所有顶点最短路径的生成树;
2、算法
(1). 普里姆算法,生成最小生成树
设图G = (V, E)所有顶点的集合为V, MST中顶点的集合为T. 1. 从G中选取任意顶点作为MST的根,将其添加至T; 2. 循环执行下述处理直至T = V 在连接T内顶点与V-T内顶点的边中选取权值最小的边(P[u], u),将其作为MST的边,并将u添加到T中,用于搜索之前未查找过的边(u作为起点);
(2).迪克斯特拉算法
求给定加权有向图G = (V, E)的单源最短路径的成本。以顶点0为起点,找出0到各顶点的最短路径上各边权值的总和。
其基本原则与普利姆算法类似 设所有的顶点集合为V,最短路径树中包含的顶点集合为S,且起点为s。 顶点s到i的最短路径为d[i],i在最短路径树中的父节点为p[i]. 循环直至S=V为止 从V-S中选出d[u]最小的顶点u; 将u添加至S中,同时将与u相邻且属于V-S中的所有顶点v的d[v]值按照如下方式更新: if d[u] + w(u, v) < d[v] d[v] = d[u] + w(u, v) p[v] = u
注意:该算法不适用于包含负权值的图,负权值的图可使用贝尔曼-福特算法或弗洛伊德算法来处理。
3. 为了改善算法复杂度,将放弃邻接矩阵来表示图的方法,而利用二叉堆(优先级队列)和邻接表表示法。
也就是采用二叉堆或者优先级队列来存放节点 Node(v, d[v]),从而可快速的取出顶点,降低算法复杂度。