Prim & Kruskal Algorithm

来源:互联网 发布:大数据与经济发展 编辑:程序博客网 时间:2024/05/20 01:34
                      **Prim算法** 

Prim算法是图论中的一种算法,可在加权连通图里搜索最小生成树。此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点,且其所有边的权值之和亦为最小。
中文名:
普里姆算法
提出时间: 1930年
外文名: Prim Algorithm
应用学科: 计算机,数据结构,数学(图论)
别称: 最小生成树算法
适用领域范围: 应用图论知识的实际问题
算法:贪心
/**********************************************************/

  • Prim算法的描述

    1).输入:一个加权连通图,其中顶点集合为V,边集合为E;
    2).初始化:Vnew = {x},其中x为集合V中的任一节点(起点),Enew= {},为空;
    3).重复下列操作,直到Vnew = V:
    a.在集合E中选取权值最小的边 (u,v),其中u为集合Vnew中的元素,而v不在Vnew集合当中,并且v∈V(如果存在有多条满足前述条件即具有相同权值的边,则可任意选取其中之一);
    b.将v加入集合Vnew中,将(u, v)边加入集合Enew中;
    4).输出:使用集合Vnew和Enew来描述所得到的最小生成树。

  • 时间复杂度:

通过邻接矩阵图表示的简易实现中,找到所有最小权边共需O(V)的运行时间。使用简单的二叉堆与邻接表来表示的话,普里姆算法的运行时间则可缩减为O(ElogV),其中E为连通图的边数,V为顶点数。如果使用较为复杂的斐波那契堆,则可将运行时间进一步缩短为O(E+VlogV),这在连通图足够密集时(当E满足Ω(VlogV)条件时),可较显著地提高运行速度。
http://blog.csdn.net/zenail501129/article/details/23551909
http://blog.csdn.net/u014488381/article/details/41447229

#include <stdio.h>#include <cstdlib>#include<memory.h>const int Max =0x7fffffff;const int N=50;int n;int g[N][N],dis[N],visited[N];int prim(){  int i,j;  int pos,min;  int ans=0;  memset(visited,0,sizeof(visited));  visited[1]=1;pos=1;  //assign a value to the dis[N] first  for(i=2;i<=n;i++)    dis[i]=g[pos][i];  for(i=1;i<n;i++)  {    min=Max;    for(j=1;j<=n;j++)    {      if(visited[j]==0&&min>dis[j])      {        min=dis[j];        pos=j;      }    }    printf("The node being traversed is :%d\n",pos);    ans+=min;    printf("The value of ans is %d\n",ans);    //mark the node    visited[pos]=1;    //update the weight    for(j=1;j<=n;j++)      if(visited[j]==0&&dis[j]>g[pos][j])        dis[j]=g[pos][j];  }  return ans;}int main(){  int i=1,j=1;  int ans=0;  int w;  printf("Please enter the number of the nodes:\n");  scanf("%d",&n);  for(i=1;i<=n;i++)    for(j=1;j<=n;j++)    {      if(i==j)        g[i][j]=0;      else        g[i][j]=Max;    }  printf("Please enter the number of the edges:\n");  int edgenum;  scanf("%d",&edgenum);  int v1,v2;  printf("Please enter the number and the corresponding weight:\n");  for(i=1;i<=edgenum;i++)  {    scanf("%d%d%d",&v1,&v2,&w);    g[v1][v2]=g[v2][v1]=w;  }  ans=prim();  printf("The sum of the weight of the edges is:%d\n",ans);  system("pause");  return 0;}

Kruskal Algorithm

#include<stdio.h>#include<stdlib.h>#include<iostream>using namespace std;#define MAXN 11     //顶点个数的最大值#define MAXM 20     //边的个数的最大值struct edge         //边{    int u, v, w;}edges[MAXM];       //边的数组int parent[MAXN];   //parent[i]为顶点i所在集合对应的树中的根结点int n, m;           //顶点个数、边的个数int i, j;           //循环变量void UFset()        //初始化{    for(i = 1; i <= n; i++) parent[i] = -1;}int Find(int x)     //查找并返回结点x所属集合的根结点{    int s;          //查找位置    for(s = x; parent[s] >=0; s = parent[s]) ;    while(s != x)   //优化方案——压缩路径,使后续的查找操作加速    {        int tmp = parent[x];        parent[x] = s;        x = tmp;    }    return s;}//运用并查集,将两个不同集合的元素进行合并,使两个集合中任意两个元素都连通void Union(int R1, int R2){    int r1 = Find(R1), r2 = Find(R2);       //r1和r2分别为R1和R2的根结点    int tmp = parent[r1] + parent[r2];      //两个集合结点数之和(负数)    //如果R2所在树结点个数 > R1所在树结点个数(注意parent[r1]是负数)    if(parent[r1] > parent[r2])    {        parent[r1] = r2;        parent[r2] = tmp;    }    else    {        parent[r2] = r1;        parent[r1] = tmp;    }}int cmp(const void *a, const void *b)       //实现从小到大的比较函数{    edge aa = *(const edge *)a, bb = *(const edge *)b;    return aa.w-bb.w;}void Kruskal(){    int sumweight = 0;      //生成树的权值    int num = 0;            //已选用的边的数目    UFset();                //初始化parent数组    for(i = 0; i < m; i++)    {        if(Find(edges[i].u) != Find(edges[i].v))        {            printf("%d %d %d\n", edges[i].u, edges[i].v, edges[i].w);            sumweight += edges[i].w; num++;            Union(edges[i].u, edges[i].v);        }        if(num >= n-1) break;    }    printf("The weight of MST is : %d\n", sumweight);}  main(){    scanf("%d%d", &n, &m);  //读入顶点个数和边数    for(int i = 0; i < m; i++)        scanf("%d%d%d", &edges[i].u, &edges[i].v, &edges[i].w); //读入边的起点和终点    printf("The edges chosen are :\n");    qsort(edges, m, sizeof(edges[0]), cmp); //对边按权值从小到大排序    Kruskal();}/**7 91 2 281 6 106 5 255 7 245 4 227 4 184 3 123 2 167 2 14**/
原创粉丝点击