• 大话数据结构 -07-3 最小生成树


     最小生成树

    一个连通图的生成树是一个极小的连通子图,它含有图中全部的顶点,但只有足以构成一棵树的n-1条边。

    把构造连通网的最小代价生成树称为最小的生成树。(最小成本,即n个顶点,用n-1条边把一个连通图连接起来,并且使得权值的和最小

    经典算法:普里姆算法和克鲁斯卡尔算法

    一、普里姆算法(Prim)

     初始化工作:

    构造最小生成树

    第一次大循环,从v0开始,找到了第一个与v0权重最小所对应的顶点,并更新了lowcost(之前记录的是邻接矩阵的第一行,大循环后更新了找到的权值最小顶点所对应的邻接矩阵的行)

    k=1,lowcost[1]=0(说明该顶点加入最小生成树) 更新后:lowcost={0,0,18,65535,65535,11,16,65535,12} adjvex={0,0,1,0,0,0,1,0,1}

    i=2时,min=11,k=5,lowcost[5]=0 (将顶点5加入生成树)。

    连接边由(adjvex[k],k)定义,即(0,5)  其中 adjvex[5]=0。

    用邻接矩阵的第五行更新lowcost={0,0,18,65535,26,0,16,65535,12} adjvex={0,0,1,0,5,0,1,0,1}

    i=3时,min =12,k=8,lowcost[8]=0 (将顶点8加入生成树)。

    连接边由(adjvex[k],k)定义,即(1,8)  其中 adjvex[8]=1

    用邻接矩阵的第8行更新lowcost={0,0,82126,0,16,65535,0} adjvex={0,0,8,85,0,1,0,1}

     

    i=4时,min =8,k=2,lowcost[2]=0 (将顶点2加入生成树)。

    连接边由(adjvex[k],k)定义,即(8,2)  其中 adjvex[2]=8

    用邻接矩阵的第2行更新lowcost={0,0,02126,0,16,65535,0} adjvex={0,0,8,85,0,1,0,1}   没有更新,第二行元素都比当前lowcost大

    i=5时,min =16,k=6,lowcost[6]=0 (将顶点2加入生成树)。

    连接边由(adjvex[k],k)定义,即(1,6)  其中 adjvex[6]=1

    用邻接矩阵的第6行更新lowcost={0,0,02126,0,0190} adjvex={0,0,8,85,0,1,6,1}   

     

    i=6时,min =19,k=7,lowcost[7]=0 (将顶点2加入生成树)。

    连接边由(adjvex[k],k)定义,即(6,7)  其中 adjvex[7]=6

    用邻接矩阵的第7行更新lowcost={0,0,0167,0,000} adjvex={0,0,8,77,0,1,6,1}   

    i=7时,min =7,k=4,lowcost[4]=0 (将顶点2加入生成树)。

    连接边由(adjvex[k],k)定义,即(7,4)  其中 adjvex[4]=7

    用邻接矩阵的第4行更新lowcost={0,0,0160,0,000} adjvex={0,0,8,77,0,1,6,1}   

     

    i=8时,min =16,k=3,lowcost[3]=0 (将顶点2加入生成树)。

    连接边由(adjvex[k],k)定义,即(7,3)  其中 adjvex[3]=7

    用邻接矩阵的第3行更新lowcost={0,0,000,0,000} adjvex={0,0,8,77,0,1,6,1}   

     

    换一种思路理解,如下:(非常重要)有助于理解代码,为什么建立两个数组lowcost和adjvex。

    二、克鲁斯卡尔算法(Kruskal)

     因为权值在边上,直接去找最小权值的边来构建生成树,但构建时要考虑是否会形成环路。

     使用边集数组存储,并按权值大小排序

    定义find函数:

    程序运行:

    i=0; begin=4;parent[4]=0,return 4,所以n=4;end=7;parent[7]=0,return 7,所以m=7;m!=n,更新parent[4]=7; 连接边(4,7)加入生成树中

    i=1; begin=2;parent[2]=0,return 2,所以n=2;end=8;parent[8]=0,return 8,所以m=8;m!=n,更新parent[2]=8; 连接边(2,8)加入生成树中

    i=2; begin=0;parent[0]=0,return 0,所以n=0;end=1;parent[1]=0,return 1,所以m=1;m!=n,更新parent[0]=1; 连接边(0,1)加入生成树中

    0 1 2 3 4 5 6 7 8
    1 0 8 0 7 0 0 0 0

    i=3; begin=0parent[0]=1>0,f=parent[0]=1,parent[1]=0;return 1,所以n=1;end=5;parent[5]=0,return 5,所以m=5;m!=n,更新parent[1]=5; 连接边(0,1)加入生成树中

    (0已经与1相连,因此将与0相连的5放置再位置1)

    0 1 2 3 4 5 6 7 8
    1 5 8 0 7 0 0 0
    0

    i=4; begin=1;parent[1]=5,parent[5]=0,return 5,所以n=5;end=8;parent[8]=0,return 8,所以m=8;m!=n,更新parent[5]=8; 连接边(1,8)加入生成树中

    0 1 2 3 4 5 6 7 8
    1 5 8 0 7 8 0 0
    0

    i=5; begin=3;parent[3]=0,return 3,所以n=3;end=7;parent[7]=0,return 7,所以m=7;m!=n,更新parent[3]=7; 连接边(3,7)加入生成树中

    0 1 2 3 4 5 6 7 8
    1 5 8 7 7 8 0 0
    0

    i=6; begin=1;parent[8]=0,return 8,所以n=8;end=6;parent[6]=0,return 6,所以m=6;m!=n,更新parent[8]=6; 连接边(1,6)加入生成树中

    0 1 2 3 4 5 6 7 8
    1 5 8 7 7 8 0 0
    6

    i=7; begin=5;parent[6]=0,return 6,所以n=6;end=6;parent[6]=0,return 6,所以m=6m==n直接跳到下一个i循环。相等是因为边(5,6)形成了循环。

    i=8; begin=1;parent[6]=0,return 6,所以n=6;end=2;parent[6]=0,return 6,所以m=6m==n直接跳到下一个i循环。相等是因为边(1,2)形成了循环。

    i=9; begin=6;parent[6]=0,return 6,所以n=6;end=7;parent[7]=0,return 7,所以m=7;m!=n,更新parent[6]=7; 连接边(6,7)加入生成树中

    0 1 2 3 4 5 6 7 8
    1 5 8 7 7 8 7 0
    6

    此后的循环均造成环路。

     

  • 相关阅读:
    windows7 下 oracle 10g服务端如何安装?
    DOM模块支持测试
    获取css属性
    在webstorm启动nginx服务器
    获取link链接
    innerText
    外部动态加载javascript
    外部动态加载css
    冒泡排序
    Nodelist
  • 原文地址:https://www.cnblogs.com/GuoXinxin/p/10512944.html
Copyright © 2020-2023  润新知