这是我参与8月更文挑战的第25天,活动详情查看:8月更文挑战
图的应用
二、最短路径
对带权图,从一个顶点𝑣0到图中其余任一顶点𝑣𝑖的一条路径(可能不止一 条)上所经过边上的权值之和定义为该路径带权路径长度,把带权路径长 度最短的那条路径称为最短路径
求解最短路径的算法通常依赖于一个性质:两点之间的最短路径也包 含了路径上其他顶点之间的最短路径
1.𝑫𝒊𝒋𝒌𝒔𝒕𝒓𝒂算法求单源最短路径问题
该算法设置一个集合S记录以求得的最短路径的结点,此外还有两个辅助数组 dist[]:记录从源点𝑣0到其他各顶点当前的最短路径长度,初始时有 dist[i]=arcs[𝑣0][i],arcs[𝑣0][i]是邻接矩阵初始值 path[]:path[i]表示从源点到顶点i之间的最短路径的前驱结点,算法结束后可根据其值追溯到源点𝑣0到顶点𝑣𝑖的最短路径 邻接矩阵arcs[][]表带权有向图,arcs[i][j]表示有向边<i,j>的权值,若不存 在边<i,j>则arcs[i][j]=∞,Dijkstra算法步骤如下: 求解最短路径的算法通常依赖于一个性质:两点之间的最短路径也包含了路径上其他顶点之间的最短路径
Dijkstra算法步骤如下:
①初始化:集合S初始化{0},dist[]初始值dist[i]=arcs[0][i],i=1,2,3,...,n-1
②从顶点集合V-S中选出v𝑗,满足dist[j]=Min{dist[i]|v𝑖 ∈ 𝑉 −𝑆}, v𝑗就是当前求得的一 条从v0出发的最短路径的终点,令S=S∪{j}
③修改从v0出发到集合V-S上任一顶点v𝑘可达的最短路径长度:如果 dist[j]+arcs[j][k]<dist[k],则更新dist[k]= dist[j]+arcs[j][k]
④重复②③操作共n-1次,直到所有顶点都包含在S中
注意:
• 若只求从源点到某一个特定顶点的最短路径仍然需要运行整个 Dijkstra算法,时间复杂度为O(|𝑉|2) • 如果要找出所有结点对之间的最短路径,时间复杂度为O(|𝑉|3) • Dijkstra算法不适合求解带负权值的图
2.Floyd算法求各顶点之间最短路径问题
注意:
- Floyd算法时间复杂度为O(|𝑉|3),虽和Dijkstra算法相比没有数量级级别的效率提升,但其代码紧凑,思想简单,故应用广泛
- Floyd算法允许图中有带负权值的边,但不允许其包含带负权值的边组成的回路
- Floyd算法也适用于带权无向图,带权无向图可看成有往返二重边的有向图
三、拓扑排序
有向无环图:一个有向图中不存在环,则称为有向无环图,简称DAG图
AOV网:如果用DAG图表示一个工程,其顶点表示活动,用有向边<𝑉𝑖,𝑉𝑗>表示活动 𝑉𝑖必须先于活动𝑉𝑗进行,则将这种有向图称为顶点表示活动的网络,记为AOV网
拓扑排序:对有向无环图的顶点的一种排序,排序规则为:
① 每个顶点出现且只出现一次
②若顶点A在序列中排在顶点B的前面,则在图中不存在从顶点B到顶点 A的路径 拓扑排序算法步骤: ①从DAG图中选择一个没有前驱(入度为0)的顶点并输出
② 从图中删除该顶点和所有以它为起点的有向边
③ 重复①②直到DAG图为空或者当前图中不存在无前驱的顶点为止, 后一种情况实际说明有向图中有环
注意:任何DAG图都有一个或多个拓扑排序序列,拓扑排序不唯一
拓扑排序算法实现
bool TopologicalSort(Graph G){
InitStack(S); //初始化栈,存储入度为0的顶点
for(int i=0;i<G.vexnum;i++)
if(indegree[i]==0)
Push(S,i); //将所有入度为0的顶点进栈
int count=0; //记录已经输出的顶点数 while(!IsEmpty(S)){
Pop(S,i);
print[count++]=i; //待输出顶点i加入输出数组暂存 for(p=G.vertices[i].firstarc;p!=NULL;p=p->nextarc){
v=p->adjvex; //将所有i指向的顶点入度减1,并将入度 if(!(--indegree[v])) //减为0的顶点压入栈S
Push(S,v);
}
}
if(count<G.vexnum)
return false; //排序失败,有向图中有回路
else return true; //拓扑排序成功
}
注意:
- 拓扑排序需要输出每个顶点的同时删除以它为起点的边,故拓扑排序时间复杂度为O(|V|+|E|)
- 拓扑排序的结果通常不唯一,但如果各个顶点已经排在一个线性有序的序列中(比如邻接表)时,拓扑排序唯一
- 由于DAG图中各个顶点地位平等,且顶点编号是人为取的,故若按照拓扑排序的结果重新安排顶点的序号,生成的DAG图的新的邻接矩阵一定是三 角矩阵
- 反之一个有向图如果它的邻接矩阵是三角矩阵,则必定存在拓扑序列