Algorithm --> Kruskal算法和Prim算法

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

  根据图的深度优先遍历和广度优先遍历,可以用最少的边连接所有的顶点,而且不会形成回路。这种连接所有顶点并且路径唯一的树型结构称为生成树或扩展树。实际中,希望产生的生成树的所有边的权值和最小,称之为最小生成树。常见的最小生成树算法有Kruskal算法和Prim算法。

Kruskal算法

每次选取权值最小的边。然后检查是否加入后形成回路,如果形成回路则需要放弃。最终构成最小生成树。n个顶点的图最小生成树步骤如下:

边的权值升序排序;

选取所有未遍历的边中权值最小的边,判断加入后是否形成回路,若形成回路,放弃之,重新从未被遍历的边中选择。

重复上述步骤,直到选中n-1条边。

代码:

/*****************Kruskal算法********************/
struct Edge
{
    int v1,v2;//顶点
    int w;//边v1--v2权值
    struct Edge *next;//指向下一条边
}
//h为按边的权值升序排序的单链表
int Kruskal(Edge *h, int *visited)
{
    int edgenum = 0;//记录生成树中边的个数
    int weight = 0;//权值和
    Edge *p = h;
    printf("最小生成树:(顶点1,顶点2,权值)\n");

    while(edgenum != maximum)//maximum=顶点数,当边数=顶点数-1时结束
    {
        if(visited[p->v1] == 0 ||visited[p->v2]==0)
            //新增边至少有一个顶点没有被访问过
        {
            printf("(%d,%d,%d)->",p->v1,p->v2,p->w);
            weight = weight + p->w; //权值和累加
            visited[p->v1] = 1;
            visited[p->v2] = 1;
            edgenum++;//边数+1
        }
        p = p->next;
        if(p==NULL)//无边可加入
        {
            printf("spanning tree fail\n");
            break;
        }
    }
    return weight;
}

Prim算法

相比于Kruskal选边生成,Prim算法选择顶点生成最小生成树。

从某个顶点v开始,列出顶点 v 所有邻接点的边 选择权值最小的边(vi-->vj)加入到最小生成树中,并标记该边已被访问过;
再从vj开始 列出顶点vj所有邻接点的边,从中选择所有未被访问过的边中权值最小的边 vj-->vk  加入到最小生成树中,并标记该边已被访问过。

重复上述操作,直到找到n-1条边为止。

代码:

/*******************Prims算法******************/
struct Edge
{
    int v1,v2;//顶点
    int w;//边v1--v2权值
    int marked;//标识该边是否已经被添加到最小生成树中
    struct Edge *next;
}
//h为边节点构成的链表,index表示开始顶点
void Prim(Edge *h,int * visited, int index)
{
    Edge *p,*min;//min每次指向剩余边中中权值最小且与上一个边共享顶点v1
    int i;
    int edgenum =0;//已连接边数
    int weight =0;//权值
    int vertex;
    min = (Edge*)malloc(sizeof(Edge));
    /***添加第一条边*******/
    min->w = h->w;//最小边权值初值(可任意指定但小于所有边的权值,当然比越大越好)
    p = h;
    while(p!=NULL)
    {
        if(p->v1 ==index && (p->w < min->w))
            min = p; //找到以index开头且权值最小的边结点
        p = p->next;
    }
    min->marked = 1;//该边已被访问
    visited[min->v1] = 1;
    visited[min->v2] = 1; //该边两个顶点被访问过
    edgenum++;
    weight = min->w;
    printf("(%d,%d,%d)->",min->v1,min->v2,min->w);//输出选中边
    /***添加其余边*******/
    while(edgenum != maximum)
    {
        min->w = h->w;
        p = h;
        while(p != NULL)
        {
            if(p->marked==0 && visited[p->v1]+visited[p->v2]==1)//边没有被访问过 且有且只有一个顶点被访问,另一顶点没有被访问过
                if(p->w < min->w)
                    min = p; //找到权值最小的边
            p = p->next;
        }
        min->marked = 1;
        visited[min->v1] =1;
        visited[min->v2] =1;
        edgenum++;
        weight += min->w;
        printf("(%d,%d,%d)->",min->v1,min->v2,min->w);
    }
    printf("\n总权值为:%d",weight);
}
时间: 2024-10-08 22:38:00

Algorithm --> Kruskal算法和Prim算法的相关文章

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

依据图的深度优先遍历和广度优先遍历,能够用最少的边连接全部的顶点,并且不会形成回路. 这样的连接全部顶点并且路径唯一的树型结构称为生成树或扩展树.实际中.希望产生的生成树的全部边的权值和最小,称之为最小生成树. 常见的最小生成树算法有Kruskal算法和Prim算法. Kruskal算法每次选取权值最小的边.然后检查是否增加后形成回路,假设形成回路则须要放弃.终于构成最小生成树.n个顶点的图最小生成树过程例如以下: 边的权值升序排序. 选取全部未遍历的边中权值最小的边,推断增加后是否形成回路,若

贪心算法-最小生成树Kruskal算法和Prim算法

Kruskal算法: 不断地选择未被选中的边中权重最轻且不会形成环的一条. 简单的理解: 不停地循环,每一次都寻找两个顶点,这两个顶点不在同一个真子集里,且边上的权值最小. 把找到的这两个顶点联合起来. 初始时,每个顶点各自属于自己的子集合,共n个子集合. 每一步操作,都会将两个子集合融合成一个,进而减少一个子集合. 结束时,所有的顶点都在同一个子集合里,这个子集合就是最小生成树. 例子: 伪代码: Prim算法: G=(V,E),S是V的真子集,如果u在S中,v在V-S中,且(u,v)是图的一

最小生成树的 Krusal 算法和 Prim 算法 Java 实现

Kruscal算法实现最小生成树 主方法 1 import java.util.Arrays; 2 import java.util.Comparator; 3 import java.util.Scanner; 4 5 public class Solution4 { 6 static class Edge{ 7 int u, v; 8 int cost; 9 }; 10 public static Edge[] edges = new Edge[10010]; // 存储所有的边的数据 11

最短路径Dijkstra算法和Floyd算法整理、

转载自:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html 最短路径—Dijkstra算法和Floyd算法 Dijkstra算法 1.定义概览 Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.Dijkstra算法是很有代表性的最短路径算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹

hdu 3864 D_num Pollard_rho算法和Miller_Rabin算法

D_num Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Problem Description Oregon Maple was waiting for Bob When Bob go back home. Oregon Maple asks Bob a problem that as a Positive number N, if there are only four

poj 3114(korasaju算法和dij算法)

Countries in War Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 2407   Accepted: 751 Description In the year 2050, after different attempts of the UN to maintain peace in the world, the third world war broke out. The importance of indus

使用Apriori算法和FP-growth算法进行关联分析(Python版)

===================================================================== <机器学习实战>系列博客是博主阅读<机器学习实战>这本书的笔记也包含一些其他python实现的机器学习算法 算法实现均采用python github 源码同步:https://github.com/Thinkgamer/Machine-Learning-With-Python ==================================

Dijkstra算法和Floyed算法

写的比较好的三篇文章 Floyed算法 最短路径-Dijkstra算法和Floyed算法 最短路径之Dijkstra算法和Floyed算法 哈哈,他山之石,可以攻玉 自己有心得,慢慢补充

链接挖掘算法之PageRank算法和HITS算法

参考资料:http://blog.csdn.net/hguisu/article/details/7996185 更多数据挖掘算法:https://github.com/linyiqun/DataMiningAlgorithm 链接分析 在链接分析中有2个经典的算法,1个是PageRank算法,还有1个是HITS算法,说白了,都是做链接分析的.具体是怎么做呢,继续往下看. PageRank算法 要说到PageRank算法的作用,得先从搜索引擎开始讲起,PageRank算法的由来正式与此相关. 搜