图的应用(Floyd算法&拓扑排序)

218 阅读2分钟

这是我参与11月更文挑战的第11天,活动详情查看:2021最后一次更文挑战

1. Floyd算法

Dijkstra算法是主要解决的是单源最短路径 而Floyd算法可以解决的是多源最短路径 他是解决任意两点间的最短路径算法(也可以解决对于权值为负的问题)--而Floyd算法是一个经典的动态规划问题 根据一个例子去了解什么是Floyd算法

Floyd算法大概的思想是这样的:把各个顶点之间的距离以二维表的形式表示出来 若vi能到vj则填写其权值 若没有可以无穷大表示即可 当选择经过一个顶点的时候就更新这张表的值(因为可能加入这个顶点 以这个顶点为辅助 vi到vj的值可以变小)若比原来值小则就更新二维数组

接下来一起来看下他算法实现吧:

void Floyd(Graph G){
  int A[G.vexnum][G.vexnum];
  for(int i=0;i<G.vexnum;i++){
    for(int j=-;j<G.vexnum;j++){
      A[i][j] = G.edge[i][j]; 
    }
  } //初始化这个二维数组
  
  for(int k=0;k<G.vexnum;k++){ //当加入某个顶点后 就要更新这个二维数组
    for(int i=0;i<G.vexnum;i++){
      for(int j=0;j<G.vexnum;j++){
         if(A[i][j] > A[i][k] + A[k][j]){ //判断加入这个顶点后vi到vj的路径是否可以变小
           A[i][j]  = A[i][k] + A[k][j] ;
         }
      }
    }
  }
}

性能分析: 时间复杂度为 O(|V|3)

2. 拓扑排序

今天想分享一个拓扑排序 拓扑排序是针对有向无环图而言的,简单来说就是Vi是Vj的前驱,要想进行活动Vj则必须完成Vi才能进行Vj 就主要是有一个顺序在里面 例如下面这个图

image.png

  1. 选择一个入度为0的顶点并输出

  2. 从网中删除该顶点和所有以它为起点的出边 再不断重复这两个步骤 故序列是这样 1,2,4,3,5

则其代码如下:

void topoSort(Graph G){
  InitStack(S); //初始化一个栈
  for(int i=0;i<G.vexnum;i++) {
    if(indegree[i]==0){
      Push(S,i)
    }
  }
  int count = 0;
  while(!isEmpty(S)){
    Pop(S,i);
    p[count++]=i;
    for(p=G.vertics[i].fristarc;p;p->nextarc){
      v=p->adjvex;
      if(!(--indegree[v])){
        Push(S,v);
      }
    }
  }
if(count<G.vexnum) {
   return false; //失败,有向图中有回路
} else {
   return true; //成功
} 
}