Prim算法的c语言实现

本文引用自泽爷工作室http://www.zeyes.org/study/clang/189.html

算法思想:

1.在把生成树看成一个集合(开始集合为空,到各个结点的距离当然未知)
2.结点与集合之间的权值可以看成结点到集合距离
3.将第一个结点加入集合,并初始化集合与其他结点的距离
4.搜索集合与结点最小的权值(距离),并把这点加入集合
5.更新集合与结点之间的距离
6.不断重复4和5步,直到所有的结点都加入了集合
(实际上把一个结点加入集合的时候,可以记录这个结点的父节点,也就是前驱,这么说吧,当找到一个与集合最小的结点的时候,他与集合中哪一结点的距离最小,把他记录来,作为生成树的路径)

算法实现:

#include <stdio.h>

#define MAXN 100

#define INF 100001 /*INF表示不存在边的长度,用一个很大的数表示它*/

void prim(int [][MAXN], int [], int); //函数原型

int main(void)

{

   int i, j, t, n;

  int w[MAXN][MAXN], fa[MAXN]; /*w是邻接矩阵,fa[x]表示是结点x的父结点)*/

  //freopen("prim.in", "r", stdin); //打开文件

  //freopen("prim.out", "w", stdout);

  scanf("%d", &n);

  for(i = 1; i <= n; i++) for(j = 1; j <= n; j++ )

  {

    scanf("%d", &t); //数据读入

    w[i][j] = (t == 0) ? INF : t;

  }

  prim(w, fa, n); //调用函数

  for(i = 2; i <= n; i++) //打印结果

  printf("%d--->%d\n", i, fa[i]);

  return 0;

  }

void prim(int w[][MAXN], int fa[], int n)

{

  int i, j, m, k; int d[MAXN]; /*d[j]可以理解成结点j到生成树(集合)的距离,它的最终值是w[j][fa[j]]*/

  for(j = 1; j <= n; j++)

  {

    d[j] = (j == 1 ? 0 : w[1][j]); /*将第一个结点加入集合,并初始化集合与其他结点的距离*/

    fa[j] = 1; /*当前集合中有且只有一个结点1,其他结点暂时未加入集合,所以没有父结点,就先姑且初始化成1*/

  }

  for(i = 2; i <=n; i++)

  {

    m = INF;

    for(j = 1; j <= n; j++)

      if(d[j] <= m && d[j] != 0) m = d[k = j]; /*选取与集合距离最小的边*/

  d[k] = 0; /*0在这里表示与集合没有距离,也就是说赋值0就是将结点k添加到集合中*/

  for(j = 1; j <= n; j++) /*对刚加入的结点k进行扫描,更新d[j]的值*/

    if(d[j] > w[k][j] && d[j] != 0)

    {

      d[j] = w[k][j];

      fa[j] = k;

    }

  }

}

时间: 2024-11-09 04:53:50

Prim算法的c语言实现的相关文章

最小生成树——Prim算法

最小生成树是图这一数据结构里最常讨论的方面之一. 先用一下几个概念回忆一下什么是最小生成树: 连通图:任意两个结点之间都有一个路径相连 生成树(Spannirng Tree):连通图的一个极小的连通子图,它含有图中全部n个顶点,但只有足以构成一棵树的n-1条边 最小生成树(Minimum Spannirng Tree):连通图的最小代价的生成树(各边的权值之和最小) 最小生成树性质(MST性质): 设G=(V,E)是一个连通网络,U是顶点集V的一个真子集.若(u,v)是G中一条"一个端点在U中(

Prim算法(一)之 C语言详解

本章介绍普里姆算法.和以往一样,本文会先对普里姆算法的理论论知识进行介绍,然后给出C语言的实现.后续再分别给出C++和Java版本的实现. 目录 1. 普里姆算法介绍 2. 普里姆算法图解 3. 普里姆算法的代码说明 4. 普里姆算法的源码 转载请注明出处:http://www.cnblogs.com/skywang12345/ 更多内容:数据结构与算法系列 目录 普里姆算法介绍 普里姆(Prim)算法,和克鲁斯卡尔算法一样,是用来求加权连通图的最小生成树的算法. 基本思想 对于图G而言,V是所

Prim算法---最小生成树

最小生成树的Prim算法也是贪心算法的一大经典应用.Prim算法的特点是时刻维护一棵树,算法不断加边,加的过程始终是一棵树. Prim算法过程: 一条边一条边地加, 维护一棵树. 初始 E = {}空集合, V = {任意节点} 循环(n – 1)次,每次选择一条边(v1,v2), 满足:v1属于V , v2不属于V.且(v1,v2)权值最小. E = E + (v1,v2)V = V + v2 最终E中的边是一棵最小生成树, V包含了全部节点. 以下图为例介绍Prim算法的执行过程. Prim

图基本算法 最小生成树 Prim算法(邻接表+优先队列STL)

这篇文章是对<算法导论>上Prim算法求无向连通图最小生成树的一个总结,其中有关于我的一点点小看法. 最小生成树的具体问题可以用下面的语言阐述: 输入:一个无向带权图G=(V,E),对于每一条边(u, v)属于E,都有一个权值w. 输出:这个图的最小生成树,即一棵连接所有顶点的树,且这棵树中的边的权值的和最小. 举例如下,求下图的最小生成树: 这个问题是求解一个最优解的过程.那么怎样才算最优呢? 首先我们考虑最优子结构:如果一个问题的最优解中包含了子问题的最优解,则该问题具有最优子结构. 最小

最小生成树问题(prim算法)POJ-1258 Agri-Net

/* 这个题很水,但是,莫名其妙runtime error一晚上,重写了一遍就又没了,很伤心! 题意很简单,大致为n个村庄,连光缆,要求连上所有村庄的长度最短. 输入n,接着是n*n的矩阵,直接用prim算法写就行: */ #include<iostream> #include<cstdlib> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath>

杭电1162--Eddy&#39;s picture(Prim()算法)

Eddy's picture Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 8070    Accepted Submission(s): 4084 Problem Description Eddy begins to like painting pictures recently ,he is sure of himself to b

无限大整数相加算法的C语言源代码

忙里偷闲,终于完成了无限大整数相加算法的C语言代码,无限大整数相加算法的算法分析在这里. 500位的加法运行1000次,不打印结果的情况下耗时0.036秒,打印结果的情况下耗时16.285秒. 下面是源码: #include <stdio.h> #include <stdlib.h> #include<string.h> #include <time.h> #define MAXNUM 1000000000000000000 /* 存储数据用的结构 long

hihocoder1097最小生成树(prim算法)

prim算法描述: prim算法的思想和代码都跟dijkstra算法非常相似. 在dijkstra算法中,我们用每次取出未标记集合中到源点最近的点进行标记并更新其邻接点到源点的距离:当d[x]+w<d[y]时更新d[y]=d[x]+w. 而在prim算法中,我们只需要对dijkstra算法稍作改动即可,即只需要改变一下更新操作:当w<d[y]时更新d[y]=w,此时d[y]的含义是节点y连接到最小生成树的边的最小取值.也就是说,从图中某个节点发出了边可能有若干条,而最终将该节点连接到最小生成树

prim算法模板

var g:array[1..10,1..10] of longint; d:array[1..10] of longint; f:array[1..10] of boolean; procedure prim; var i,j,k,min:longint; begin fillchar(g,sizeof(g),0); fillchar(f,sizeof(f),0); for i:=1 to n do d[i]:=g[1,i]; f[1]:=true; for i:=2 to n do begi