最小生成树的两种构造方法.docx
《最小生成树的两种构造方法.docx》由会员分享,可在线阅读,更多相关《最小生成树的两种构造方法.docx(9页珍藏版)》请在冰豆网上搜索。
最小生成树的两种构造方法
离散数学大作业
---最小生成树
姓名:
陈强
学号:
辅导老师:
李阳阳
一、最小生成树的概念:
给定一个连通图,要求构造具有最小代价的生成树时,也即使生成树各边的权值总和达到最小。
把生成树各边的权值总和定义为生成树的权,那么具有最小权值的生成树就构成了连通图的最小生成树,最小生成树可简记为MST。
二、构造无向连通图的最小生成树的方法:
1.Prim(普里姆)算法
算法:
假设G(V,E)是有n个顶点的无向连通图,用T(U,TE)表示要构造的最小生成树,其中U为顶点集合,TE为边的集合。
(1)初始化:
令V={
},TE={
}。
从V中取一个顶点u0放入生成树的顶点集U中,作为第一个顶点,此时T=({u0},{
});
(2)从
的边(u,v)中找一条代价最小的边
,将其放入TE中,并将
放入U中。
(3)重复步骤
(2),直至U=V为止。
此时TE集合中必有n-1条边,T即为所要构造的最小生成树。
特殊处理:
如果两个顶点之间没有直接相连的边,权值置为一个max的数
自身和自身的权值置为MAX的值
代码:
function[T]=Prim(i,G_dist)
%Prim.m实现了普里姆的方法生成无向连通图G的最小生成树
%T是返回的最小生成树
%i为输入的为最小生成树选定的第一个顶点
%G_dist是待输入的数据,是图G边(u,v)的权值矩阵
[m,n]=size(G_dist);%读入无向图的顶点数目为m=n
v=i;%将选定的顶点放入中间变量v中
T=zeros(3,m-1);%最小生成树有(m-1)条边。
第一行存放边的起点,第二行存放边的终点,第三行存放边的权值
%%
%初始化最小生成树的矩阵
forj=1:
m-1
T(1,j)=v;%将第一个顶点放入最小生成树的矩阵中
ifj>=v
T(2,j)=j+1;
T(3,j)=G_dist(v,j+1);
else
T(2,j)=j;
T(3,j)=G_dist(v,j);
end
end
%%
%求第k条边
fork=1:
(n-1)
min=10000;%初始化一个最小的权值
%找出最短边,并将最短变的下标记录在mid中
forj=k:
(n-1)
ifT(3,j)min=T(3,j);
mid=j;
end
end
e=T(:
mid);T(:
mid)=T(:
k);T(:
k)=e;%将最短的边所在的一列和第k列交换
v=T(2,k);%v中存放新找到的最短边在V-U中的顶点
forj=(k+1):
(n-1)%修改所存储的最小边集
d=G_dist(v,T(2,j));
ifdT(3,j)=d;T(1,j)=v;
end
end
end
DG=sparse(T(1,:
),T(2,:
),T(3,:
),m,m);%用稀疏矩阵
view(biograph(DG,[],'ShowArrows','off','ShowWeights','on'));%画图
调用函数
G=[10000,10,3,10000,10000,10000;10,10000,5,8,6,10000;3,5,10000,10000,2,10000;10000,8,10000,10000,7,11;10000,6,2,7,10000,17;10000,10000,10000,11,17,10000;];
%G表示图G的各边权值,自身到自身的权值和不直接相连的顶点的权值设为10000
i=1;
T1=[1,2,1,3,2,2,4,4,5;3,3,2,5,5,4,5,6,6;3,5,10,2,6,8,7,11,17;0,0,0,0,0,0,0,0,0];
%T1表示图G的边的信息,第一行是边的起始点,第二行是边的终点,第三行是边的权重,第四行表示对边的选择
T=T1(1:
3,:
);
DG=sparse(T1(1,:
),T1(2,:
),T1(3,:
),m,m);%用稀疏矩阵
view(biograph(DG,[],'ShowArrows','off','ShowWeights','on'));%画图
Prim(i,G);
结果:
图G:
Prim生成的最小生成树:
2.Kruskal(克鲁斯卡尔)算法
算法:
假设G(V,E)是有n个顶点的无向连通图。
(1)初始化:
设置最小生成树的初始状态为只有n个顶点而无任何边的非连通图T(V,{
})。
(2)依次选择E中的最小代价边,若该代价边依附于T中两个不同的连通分量,则将该边加入TE中。
否则,舍去此边而选择下一条代价最小的边。
(3)重复步骤
(2)直到所有顶点都在同意连通分量上为止。
这时T就是G的一棵最小生成树。
代码:
function[T]=Kruscal(T1,e,m)
%Kruscal.m实现了克鲁斯克尔的方法生成无向连通图G的最小生成树
%T是返回的最小生成树
%T1是图G的边信息
%e表示的是图G中的边的数目
%m是图G的顶点数目
%%
%初始化存放顶点连通信息的矩阵GG
GG=zeros(1,m);
fori=1:
m
GG(i)=i;
end
%%
j=0;
%直到选够(m-1)条边即可结束程序
%whilejfori=1:
e
ifT1(4,i)==0
k=T1(1,i);l=T1(2,i);T1(4,i)=1;%更新最小代价值,将改变标记为已经选择过的边
end
ifGG(k)==GG(l)
T1(4,i)=2;%标记为2的边为舍去的边
else
j=j+1;
%将最短边的两个顶点并入同一分量
L=GG(l);
fort=1:
m
ifGG(t)==L;
GG(t)=GG(k);
end
end
end
ifj>=m-1
break;
end
end
fori=1:
e
ifT1(4,i)==2||T1(4,i)==0
T1(:
i)=[0;0;0;0];
end
end
T1=T1(:
any(T1));
T=T1(1:
3,:
);
DG=sparse(T1(1,:
),T1(2,:
),T1(3,:
),m,m);%用稀疏矩阵
view(biograph(DG,[],'ShowArrows','off','ShowWeights','on'));%画图
调用函数
e=9;%图G的边的数目
m=6;%图G的顶点数目
T1=[1,2,1,3,2,2,4,4,5;3,3,2,5,5,4,5,6,6;3,5,10,2,6,8,7,11,17;0,0,0,0,0,0,0,0,0];
%T1表示图G的边的信息,第一行是边的起始点,第二行是边的终点,第三行是边的权重,第四行表示对边的选择
T=T1(1:
3,:
);
DG=sparse(T1(1,:
),T1(2,:
),T1(3,:
),m,m);%用稀疏矩阵
view(biograph(DG,[],'ShowArrows','off','ShowWeights','on'));%画图
T1=T1';
T1=sortrows(T1,3);%将T1的转置按照权值生序排列
T1=T1';%转置回来
Kruscal(T1,e,m);
结果:
图G:
Kruscal最小生成树: