最小生成树-普林算法(Prim)/克鲁斯卡尔算法(Kruskal)

问题提出:

        一个公司计划建立一个通信网络来连接它的一个计算机中心。可以用租用的电话线连接这些中心的任何一对。应当妊娠瘙痒哪些连接,以便保证在任何两个计算机中心之间都有通路,且网络的总成本最小?可以用下较长所示的带权图为这个问题建模,其中顶点表示计算机中心,边表示可能租用的电话线,边上的权是边所表示的电话线的月租费。通过找出一棵生成树,使得这棵树的各边的权之和为最小,就可以解决这个问题。这样的生成树称为最小生成树。

最小生成树定义:
    在一个具有V个节点的连通无向图中,找到一个子图,该子图包含原图的所有节点和部分连接边,且不能形成回路,同时子图边的权值总和最小。
最小生成树的算法:
根据对安全边的不同规则,有两种算法可以生成最小生成树。即Kruskal算法和Prim算法。

1.普林算法(Prim)

        该算法所具有的一个性质是集合A中的边总是构成一棵树,而不是森林。这棵树从任意一个根节点开始,一直长大到覆盖V中所有的节点为止。算法每一步在链接集合A和A之外的节点的边,选择一条轻量级边加入到集合A中。
步骤:
设是带权值的连通图,A是上最小生成树中边的集合:
(1)初始令,(), A=NULL
(2)在所有,的边中,找一条权值最小的边
(3)将并入集合A,同时并入
(4)重复上述操作直至为止,则为的最小生成树
判断规则:在所有,的边中,找一条权值最小的边,连接该边,但不能形成回路;


举例:
最小生成树-普林算法(Prim)/克鲁斯卡尔算法(Kruskal)_第1张图片
该图为原始图
第一步:选取一个初始节点a为根节点,并找到权值为最小的边,即为ab;
最小生成树-普林算法(Prim)/克鲁斯卡尔算法(Kruskal)_第2张图片

第二步:在所有,的边中,找一条权值最小的边;即权值最小边为bc或者ah;这里选取bc
最小生成树-普林算法(Prim)/克鲁斯卡尔算法(Kruskal)_第3张图片

第三步:在所有,的边中,找一条权值最小的边;即选择ci;
最小生成树-普林算法(Prim)/克鲁斯卡尔算法(Kruskal)_第4张图片

第四步:在所有,的边中,找一条权值最小的边;即选择cf;
最小生成树-普林算法(Prim)/克鲁斯卡尔算法(Kruskal)_第5张图片

第五步:在所有,的边中,找一条权值最小的边;即选择fg;

最小生成树-普林算法(Prim)/克鲁斯卡尔算法(Kruskal)_第6张图片
第六步:在所有,的边中,找一条权值最小的边;即选择gh;

最小生成树-普林算法(Prim)/克鲁斯卡尔算法(Kruskal)_第7张图片
第七步:在所有,的边中,找一条权值最小的边;必须保证不能形成回路,即选择cd;
最小生成树-普林算法(Prim)/克鲁斯卡尔算法(Kruskal)_第8张图片



最后一步:在所有,的边中,找一条权值最小的边;必须保证不能形成回路,即选择de;由于树包含了所有节点,且满足,则在此终止,为的最小生成树。
最小生成树-普林算法(Prim)/克鲁斯卡尔算法(Kruskal)_第9张图片
         很简单的地说,就是建立一棵树T,和不在树中的顶点集合L,找出两者之间最短的距离的点,加入到树中,直到所有点加进去为止。
//d为图的邻近矩阵,p为所生成树的邻近矩阵,
//n为图中点的个数
void Prim(int **d,int **p,int n)
{
	int i,j,tmp,iT,iL;
	vector T,L;//T是要生成的树,L为还没生成树的顶点
	for(i=0;i=0;j--){
				if(tmp>=d[T[i]][L[j]]){
					tmp=d[T[i]][L[j]];
					iT=i;iL=j;
				}
			}
		}
		cout<

最小生成树-普林算法(Prim)/克鲁斯卡尔算法(Kruskal)_第10张图片
时间复杂度:
最小边、权的数据结构 时间复杂度(总计)
邻接矩阵、搜索 O(V2)
二叉堆、邻接表 O((V + E) log(V)) = O(E log(V))
斐波那契堆、邻接表 O(E + V log(V))

2.克鲁斯卡尔算法(Kruskal)



3.网络资源

http://blog.csdn.net/chenhanzhun/article/details/39006205
http://blog.csdn.net/niushuai666/article/details/6689285
http://baike.baidu.com/view/247951.htm?fr=aladdin

你可能感兴趣的:(最小生成树-普林算法(Prim)/克鲁斯卡尔算法(Kruskal))