Prim算法和Kruskal算法都能从连通图找出最小生成树。区别在于Prim算法是以某个顶点出发挨个找,而Kruskal是先排序边,每次选出最短距离的边再找。

一、Prim(普里姆算法)算法:

Prim算法实现的是找出一个有权重连通图中的最小生成树,即:具有最小权重且连接到所有结点的树。(强调的是树,树是没有回路的)。

Prim算法是这样来做的:

首先以一个结点作为最小生成树的初始结点,然后以迭代的方式找出与最小生成树中各结点权重最小边,并加入到最小生成树中。加入之后如果产生回路则跳过这条边,选择下一个结点。当所有结点都加入到最小生成树中之后,就找出了连通图中的最小生成树了。

Prim算法最小生成树查找过程:

C语言实现:

#include <stdio.h>
#include <stdlib.h>
#define maxint 1073741824
int main()
{
  FILE *input=fopen("input.txt","r"),*out=fopen("output.txt","w");
  int n,m,i,j,x,y,w;
  fscanf(input,"%d %d",&n,&m);
  int map[n][n],E[m][3],tree[m],Mst[n][n];
  /*Mst表示最小生成树的邻接矩阵,map是原图,E是边集,其中E[0]和E[1]是边的两个顶点,E[2]是边的权值,tree是用于判断原图的点是否在最小生成树中*/
  memset(tree,0,sizeof(tree));
  for(i=0; i<n; i++)
  {
   for(j=0; j<n; j++)
   {
   map[i][j]=maxint;
   Mst[i][j]=maxint;
    }
   E[i][0]=E[i][1]=maxint;
  }
  for(i=0; i<m; i++)
  {
   fscanf(input,"%d %d %d",&x,&y,&w);
   if(w<map[x][y])
   {
   map[x][y]=w;
   map[y][x]=w;
   }
  }
  int min=maxint,next=0,now=0,k=0;
  tree[0]=1;
  for(i=0; i<n; i++)
  {
   for(j=0; j<n; j++)
   {
   if(map[now][j]!=maxint && tree[j]==0)
   {
   E[k][0]=now;
   E[k][2]=map[now][j];
   E[k++][1]=j;
   }
   }
   for(j=0; j<k; j++)
   {
   if(E[j][2]<min && tree[E[j][1]]==0)
   {
   min=E[j][2];
   x=E[j][0];
   y=E[j][1];
   next=y;
   }
   }
   tree[next]=1;
   now=next;
   Mst[x][y]=map[x][y];
   Mst[y][x]=map[y][x];
   min=maxint;
  }
  for(i=0; i<n; i++)
  {
   for(j=0; j<n; j++)
   {
   if(Mst[i][j]==maxint) //判断两点是否连通
   fprintf(out,"00 "); //美化输出,不必多加探究
   else
   {
   fprintf(out,"%d ",Mst[i][j]); //输出生成树的邻接矩阵,要输出树的自己可以根据邻接矩阵的数据进行加工
   }
   }
   fprintf(out,"\n");
  }
  fclose(input);
  fclose(out);
  return 0;
} // 程序未考虑不是连通图的情况,修改很简单,判断生成树的节点数量是否等于原图的节点数量
  //如果小于(不会有大于)则本图不是连通图
  //其实prim和迪杰斯特拉算法核心有相似之处

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

Kruskal算法与Prim算法的不同之处在于,Kruskal在找最小生成树结点之前,需要对所有权重边做从小到大排序。将排序好的权重边依次加入到最小生成树中,如果加入时产生回路就跳过这条边,加入下一条边。当所有结点都加入到最小生成树中之后,就找出了最小生成树。

C语言实现:

/*  Kruskal.c
  Copyright (c) 2002, 2006 by ctu_85
  All Rights Reserved.
I am sorry to say that the situation of unconnected graph is not concerned
*/
#include "stdio.h"
#define maxver 10
#define maxright 100
int G[maxver][maxver],record=0,touched[maxver][maxver];
int circle=0;
int FindCircle(int,int,int,int);
int main()
{
int path[maxver][2],used[maxver][maxver];   int i,j,k,t,min=maxright,exsit=0;
  int v1,v2,num,temp,status=0;
  restart:
  printf("Please enter the number of vertex(s) in the graph:\n");
  scanf("%d",&num);
  if(num>maxver||num<0)
  {
   printf("Error!Please reinput!\n");
   goto restart;
  }
  for(j=0;j<num;j++)
   for(k=0;k<num;k++)
   {
   if(j==k)
   {
   G[j][k]=maxright;
   used[j][k]=1;
   touched[j][k]=0;
   }
   else
   if(j<k)
   {
   re:
   printf("Please input the right between vertex %d and vertex %d,if no edge exists please input -1:\n",j+1,k+1);
   scanf("%d",&temp);
   if(temp>=maxright||temp<-1)
   {
   printf("Invalid input!\n");
   goto re;
   }
   if(temp==-1)
   temp=maxright;
   G[j][k]=G[k][j]=temp;
   used[j][k]=used[k][j]=0;
   touched[j][k]=touched[k][j]=0;
   }
   }
   for(j=0;j<num;j++)
   {
   path[j][0]=0;
   path[j][1]=0;
   }
   for(j=0;j<num;j++)
   {
   status=0;
   for(k=0;k<num;k++)
   if(G[j][k]<maxright)
   {
   status=1;
   break;
   }
   if(status==0)
   break;
   }
   for(i=0;i<num-1&&status;i++)
   {
   for(j=0;j<num;j++)
   for(k=0;k<num;k++)
   if(G[j][k]<min&&!used[j][k])
   {
   v1=j;
   v2=k;
   min=G[j][k];
   }
   if(!used[v1][v2])
   {
   used[v1][v2]=1;
   used[v2][v1]=1;
   touched[v1][v2]=1;
   touched[v2][v1]=1;
   path[0]=v1;
   path[1]=v2;
   for(t=0;t<record;t++)
   FindCircle(path[t][0],path[t][0],num,path[t][0]);
   if(circle)
   {/*if a circle exsits,roll back*/
   circle=0;
   i--;
   exsit=0;
   touched[v1][v2]=0;
   touched[v2][v1]=0;
   min=maxright;
   }
   else
   {
   record++;
   min=maxright;
   }
   }
  }
  if(!status)
  printf("We cannot deal with it because the graph is not connected!\n");
  else
  {
   for(i=0;i<num-1;i++)
   printf("Path %d:vertex %d to vertex %d\n",i+1,path[0]+1,path[1]+1);
  }
  return 1;
}
int FindCircle(int start,int begin,int times,int pre)
{ /* to judge whether a circle is produced*/
  int i;
  for(i=0;i<times;i++)
  if(touched[begin]==1)
  {
   if(i==start&&pre!=start)
   {
   circle=1;
   return 1;
   break;
   }
  else
   if(pre!=i)
   FindCircle(start,i,times,begin);
   else
   continue;
  }
  return 1;
}

无疑,Kruskal算法在效率上要比Prim算法快,因为Kruskal只需要对权重边做一次排序,而Prim算法则需要做多次排序。尽管Prim算法每次做的算法涉及的权重边不一定会涵盖连通图中的所有边,但是随着所使用的排序算法的效率的提高,Kruskal算法和Prim算法之间的差异将会清晰的显性出来。

Prim算法和Kruskal算法的更多相关文章

  1. 转载:最小生成树-Prim算法和Kruskal算法

    本文摘自:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/30/2615542.html 最小生成树-Prim算法和Kruskal算法 Prim算 ...

  2. 最小生成树之Prim算法和Kruskal算法

    最小生成树算法 一个连通图可能有多棵生成树,而最小生成树是一副连通加权无向图中一颗权值最小的生成树,它可以根据Prim算法和Kruskal算法得出,这两个算法分别从点和边的角度来解决. Prim算法 ...

  3. java实现最小生成树的prim算法和kruskal算法

    在边赋权图中,权值总和最小的生成树称为最小生成树.构造最小生成树有两种算法,分别是prim算法和kruskal算法.在边赋权图中,如下图所示: 在上述赋权图中,可以看到图的顶点编号和顶点之间邻接边的权 ...

  4. 最小生成树——Prim算法和Kruskal算法

    洛谷P3366 最小生成树板子题 这篇博客介绍两个算法:Prim算法和Kruskal算法,两个算法各有优劣 一般来说当图比较稀疏的时候,Kruskal算法比较快 而当图很密集,Prim算法就大显身手了 ...

  5. 最小生成树Prim算法和Kruskal算法

    Prim算法(使用visited数组实现) Prim算法求最小生成树的时候和边数无关,和顶点树有关,所以适合求解稠密网的最小生成树. Prim算法的步骤包括: 1. 将一个图分为两部分,一部分归为点集 ...

  6. 【数据结构】最小生成树之prim算法和kruskal算法

    在日常生活中解决问题经常需要考虑最优的问题,而最小生成树就是其中的一种.看了很多博客,先总结如下,只需要您20分钟的时间,就能完全理解. 比如:有四个村庄要修四条路,让村子能两两联系起来,这时就有最优 ...

  7. Prim算法和Kruskal算法的正确性证明

    今天学习了Prim算法和Kruskal算法,因为书中只给出了算法的实现,而没有给出关于算法正确性的证明,所以尝试着给出了自己的证明.刚才看了一下<算法>一书中的相关章节,使用了切分定理来证 ...

  8. 最小生成树---Prim算法和Kruskal算法

    Prim算法 1.概览 普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树.意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(英语:Vertex (gra ...

  9. prim 算法和 kruskal算法

    Prim算法 1.概览 普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树.意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(英语:Vertex (gra ...

随机推荐

  1. Linux下/etc/passwd、/etc/shadow、/etc/group文件

    1./etc/passwd [root@prac ~]# cat /etc/passwd root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbi ...

  2. 何凯文每日一句打卡||DAY14

  3. Your Prediction Gets As Good As Your Data

    Your Prediction Gets As Good As Your Data May 5, 2015 by Kazem In the past, we have seen software en ...

  4. python学习笔记6--操作Mysql

    一.mysql操作 import pymysql #连上mysql ip 端口号 密码 账号 数据库 #建立游标 #执行sql #获取结果 #关闭连接.关闭游标 conn=pymysql.connec ...

  5. 【整理】HTML5游戏开发学习笔记(2)- 弹跳球

    1.预备知识(1)在画布上绘制外部图片资源(2)梯度(gradient):HTML5中的对象类型,包括线性梯度和径向梯度.如createLinearGradient,绘制梯度需要颜色组http://w ...

  6. [R语言]读取文件夹下所有子文件夹中的excel文件,并根据分类合并。

    解决的问题:需要读取某个大文件夹下所有子文件夹中的excel文件,并汇总,汇总文件中需要包含的2部分的信息:1.该条数据来源于哪个子文件夹:2.该条数据来源于哪个excel文件.最终,按照子文件夹单独 ...

  7. Nginx使用笔记

    本篇记录使用Nginx的一些tricks. 一.更改默认Web根目录 修改配置文件 Nginx默认的Web根目录是:/usr/share/nginx/html/,一般我们都是习惯的是:/var/www ...

  8. js 判断日期大小、是否在时间范围内等处理

    var beginval="2015-09-01";//这个时间可以是日期控件选择的,也可以是其他的任何日期时间 var endval="2015-09-01" ...

  9. 日期控件-my97DatePicker用法

    网上资料,用法,只能选最近30天等等:http://jingyan.baidu.com/article/e6c8503c7244bae54f1a18c7.html

  10. (F. MST Unification)最小生成树

    题目链接:http://codeforces.com/contest/1108/problem/F 题目大意:给你n个点和m条边,然后让你进行一些操作使得这个图的最小生成树唯一,每次的操作是给某一条边 ...