数据结构--最小生成树

假设要在n个城市之间建立通信联络网,则联通n个城市需要n-1条线路。这时需要考虑如何建设才能最省钱呢?用连通网来表示n个城市及n个城市间可能设置的通信线路,其中网的顶点表示城市,边表示城市间的线路,边的权值表示建造这条线路的花费。对于n个顶点的连通网可以建立许多不同的生成树,每棵生成树都可以是一个通信网,选择一棵总耗费最小的生成树,就是最小代价生成树(最小生成树minimum cost spanning tree)。一棵生成树的代价就是树上各边的代价之和。
下面介绍构造最小生成树的算法。
一、普里姆(Prim)算法
1、算法思想


image.png

上图为原始的连通网,从中选取合适的路径构造最小生成树。
初始时:属于最小生成树的顶点集合U = { }
不属于最小生成树的集合V = {v1、v2、v3、v4、v5、v6}
设置两个数据结构:
lowcost[i]:表示以i为终点的边的最小权值,lowcost[i] = 0表示以i为终点的边的最小权值为0,也就说i点加入了最小生成树。
mst[i]:表示对应lowcost[i]那条边的起点,(mst[i],i)表示的就是最小生成树的一条边,当mst[i] = 0表示起点i加入了最小生成树。

第一步:选择顶点v1作为起始点
这时:属于最小生成树的顶点集合U = {v1}
不属于最小生成树的集合V = {v2、v3、v4、v5、v6}
以顶点v1作为起点的边有(1,2),(1,3),(1,4),也就是终端点为2,4,5,
把权值赋到lowcost中,lowcost[2]=6,lowcost[3]=1,lowcost[4]=5,lowcost[5]=,lowcost[6]=,(*代表无限大,即无通路)
mst赋默认值:mst[2]=1,mst[3]=1,mst[4]=1,mst[5]=1,mst[6]=1

image.png

第二步:以顶点v1为起始点找到一条权值最小的边,这条边的要求是一个顶点在集合U,一个顶点在集合V,这条边就是顶点v1到顶点v3的一条边
这时:属于最小生成树的顶点集合U = {v1、v3}
不属于最小生成树的集合V = {v2、v4、v5、v6}
(1,3)这条边的权值最小,加入集合,更新lowcost,mst数据
lowcost[2]=5,lowcost[3]=0(已加入集合,赋值为0),lowcost[4]=5,lowcost[5]=6,lowcost[6]=4
mst[2]=3,mst[3]=0(已加入集合,赋值为0),mst[4]=1,mst[5]=3,mst[6]=3
image.png

第三步:重复上面步骤
这时:属于最小生成树的顶点集合U = {v1、v3、v6}
不属于最小生成树的集合V = {v2、v4、v5}
image.png

这时:属于最小生成树的顶点集合U = {v1、v3、v6、v4、v2}
不属于最小生成树的集合V = {v5}
为什么会选择顶点v3-v5这个边?
经过上步,还有顶点v2、顶点v5没有连上,U中与顶点v2相连的为顶点v1(权值为6),顶点v3(权值为5),U中与顶点v5相连的为顶点v3、顶点v6,(权值均为6),选取权值最小的边,所以把顶点v3与顶点v2相连,并把顶点v2加入到U中
image.png

最后:属于最小生成树的顶点集合U = {v1、v3、v6、v4、v2、v5}
不属于最小生成树的集合V = { }

2、算法

int prim(int graph[][MAX], int n)  {  
    int lowcost[MAX];  
    int mst[MAX];  
    int i, j, min, minid, sum = 0;  
    for (i = 2; i <= n; i++)  {  //lowcost赋值为起点为v1的边的权值
        lowcost[i] = graph[1][i];  
        mst[i] = 1;  
    }  
    mst[1] = 0;  //顶点v1加入集合
    for (i = 2; i <= n; i++)  {  
        min = MAXCOST;  
        minid = 0;  
        for (j = 2; j <= n; j++)   {  
          //找到未被访问的,且权值最小的顶点
            if (lowcost[j] < min && lowcost[j] != 0)  {  
                min = lowcost[j];  
                minid = j;  
            }  
        }  
        sum += min;  
        lowcost[minid] = 0;  //加入集合
        for (j = 2; j <= n; j++)   {  
          //更新lowcost,mst
            if (graph[minid][j] < lowcost[j])  {  
                lowcost[j] = graph[minid][j];  
                mst[j] = minid;  
            }  
        }  
    }  
    return sum;  
}  

算法复杂度为O(n2),与网中的边数无关,适用于求边稠密的网的最小生成树。

二、克鲁斯卡尔(Kruskal)算法
1、算法思想
(1)一个有n个顶点的连通网络N = (V, {E}),最初先构造一个只有n个顶点,没有边的非连通图T = {V, {ф}},图中每个顶点自成一格连通分量。
(2)在E中选择一条具有最小权植的边,若该边的两个顶点落在T中不同的连通分量上,则将此边加入到T中;否则将此边舍去,重新选择一条权植最小的边。
(3)以此类推,直到T中所有顶点在同一连通分量上为止。


image.png

上图为原始的连通网,从中选取合适的路径构造最小生成树。
第一步:只有6个顶点而没有边的非连通图,每个顶点都是一个连通分量,一共有6个(红色圆圈)


image.png

第二步:选择一条权值最小的边(v1,v3),这条边连接了两个连通分量,因此连通分量变成了5个


image.png

第三步:在剩下的边中,再选择一条权值最小的边(v4, v6),这条边连接了两个连通分量,也没有构成回路,所以是符合要求的,这时连通分量变成了4个
image.png

第四步:在剩下的边中,再选择一条权值最小的边(v2, v5),这条边连接了两个连通分量,也没有构成回路,所以是符合要求的,这时连通分量变成了3个
image.png

第五步:在剩下的边中,再选择一条权值最小的边(v3, v6),这条边连接了两个连通分量,也没有构成回路,所以是符合要求的,这时连通分量变成了2个


image.png

最后一步:在剩下的边中,再选择一条权值最小的边(v2, v3),这条边连接了两个连通分量,也没有构成回路,所以是符合要求的,得到最终的最小生成树。(剩下的边中,权值最小边有:(v2, v3),(v3, v4)和(v1, v4),选择(v2, v3)是因为只有这条边不会构成回路。)
image.png

算法复杂度为O(eloge)(e为网中边的数目),适合求边稀疏的网的最小生成树
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容