数据结构与算法之图(下)

最小生成树

在这里插入图片描述
树有一个特点:有n个节点,就有n-1条边。这显然是把n个节点连起来的最少边数,之所以在图当中提到这个,是为了解决图当中将所有联通的顶点连接起来,要求这些边的权重加起来最小的问题。权重和最小这个要求听上去好像是有点耳熟啊,没错,之前讲迪杰特斯拉算法就是解决了单源最短路径的问题,那条路径是那两点之间权重加起来最小的,但他并不一定将整个连通图里的顶点都包含进去了。不过我们可以依照一样的思想去做,这就产生了一个新的算法:普里姆算法。

普里姆算法(Prim)

在这里插入图片描述
比如这里我们选取V1为起点,进到算法里面来之后,我们先找到与之相关联的点跟谁的边权重最小就将这条边存入Path数组,这个时候树就长大了一点,再看与这棵小树相关的哪条边权重最小,这里V1V2,V3V4都是2,先选谁没关系啊,树又长大了,2的找完了那V4V2的3这条边能不能选呢,是不能的,最小生成树当中是不允许又环路存在的,慢慢的最小生成树就长成了。

克鲁斯卡尔算法

在这里插入图片描述
克鲁斯卡尔算法是一种新的思想,他不断的将森林合并,最终一个连通图里只会有一棵树,这就是最小生成树,过程是这样的,他先找到图中最小的边,这里面找到了V1V4和V6V7,他们两个都是最小的,他们两个就是两棵树了,然后不断重复,注意不要形成环路,最后所有节点都在树里之后就形成了最小的生成树。
在这里插入图片描述
找权重最小的边用前面讲到的最小堆,时间复杂度会比排序低些,构不构成回路可以利用并查集看他们在不在一个点集里。

拓扑排序

在这里插入图片描述
拓扑排序其实就是把各个顶点按入度从小到大进行排序,朴素做法的过程就是先把每个点的入度数出来,遍历找到入度为零的点输出或记录将其入度改为-1,并将与之有关的点的入度减一,让后再从头开始遍历,直到所有点遍历完。但他时间复杂度开了O(n2)。
在这里插入图片描述
所以我们用队列这个容器来优化这个算法(跟之前的BFS里队列的使用差不多)
在这里插入图片描述
康康代码:

void topsort(int v)
{
 for(int i=1;i<=v;i++)
    for(int j=1;j<=v;j++)
       if(map[i][j])
         rudu[j]++;
 int k;
 for(int i=1;i<=v;i++)
 {
    for(int j=1;j<=v;j++)
    {
       if(rudu[j]==0)
       {
           k=j;
           break;
       }
    }
    path[i]=k;
    rudu[k]=-1;
    for(int j=1;j<=v;j++)
    {
       if(map[k][j])
          rudu[j]--;
    }
 }
}
发布了32 篇原创文章 · 获赞 5 · 访问量 891

猜你喜欢

转载自blog.csdn.net/LebronGod/article/details/104472417