kruskal算法的实现

一.概述

kruskal算法是计算一副加权无向图的最小生成树的另外一种算法,它的主要思想是按照边的权重(从小到大)处理它们,将边加入最小生成树中,加入的边不会与已经加入最小生成树的边构成环 ,直到树中含有V-1条边为止。

kruskal算法和prim算法的区别:
Prim算法是一条边一条边的构造最小生成树,每一步都为一棵树添加一条边。
kruskal算法构造最小生成树的时候也是一条边一条边地构造,但它的切分规则是不一样的:

kruskal将多个顶点看作多颗树,它每一次寻找的边会连接一片森林中的两棵树。如果一副加权无向图由V个顶点组成,初始化情况下每个顶点都构成一棵独立的树,则V个顶点对应V棵树,组成一片森林,kruskal算法每一次处理都会将两棵树合并为一棵树,直到整个森林中只剩一棵树为止。

kruskal算法的实现原理:

在设计API的时候,使用了一个最小优先队列MinPriorityQueue pq存储图中所有的边,
每次使用pq.delMin()取出权重最小的边(同时会删除pq中最小的那条边)
并得到该边关联的两个顶点vw,通过uf.connect(v,w)判断v和w是否已经连通:


  • 如果连通,则证明这两个顶点在同一棵树中,那么就不能再把这条边添加到最小生成树中,因为在一棵树的任意两个顶点上添加一条边,都会形成环,而最小生成树不能有环的存在。不做操作。

  • 如果不连通,则通过uf.connect(v,w)把顶点v所在的树和顶点w所在的树合并成一棵树,并把这条边加入到mst队列中,这样如果把所有的边处理完,最终mst中存储的就是最小生树的所有边。

例:

在这里插入图片描述
找到当前权重最小的边并删除该边,以及顶点0、7
判断两个顶点是否在同一棵树中,此时不在,则合并0和7所在的树

在这里插入图片描述
继续找权重最小的边,找到2、3所在边并删除该边
判断2、3是否在同一棵树上,没有,则合并2、3所在组

。。。。。
在这里插入图片描述
直到所有顶点都处于同一棵树中。
此时再找出权重最小的0、6所在的边并删除
判断0、6是否在同一个组,是,则不做任何处理,同理…

二.实现

在这里插入图片描述

public class kruskal {
    private Queue<Edge> mst; //保存最小生成树的所有边
    private uf uf; //并查集,索引代表顶点,值代表组的标识,可用conn判断顶点是否在一棵树中,使用union可以合并
    private minPriorityQueue<Edge> pq; //最小优先队列, 存储图中所有的边,按照权重进行排序,可以找到权重最小的边


    public kruskal(pathWeight g) { //参数为加权无向图
        this.mst = new LinkedList<>();
        uf = new uf(g.V());
        this.pq = new minPriorityQueue(g.E()); //最小优先队列存的是 边!
        //把图中所有的边存入pq
        for (Edge k : g.edges()) { //edges会获取所有边放入一个队列
            pq.insert(k);
        }

        //遍历pq队列,拿到权重最小的边,进行处理
        while (!pq.isEmpty() && mst.size() < g.V() - 1) {  
        //当边的数量=顶点数量-1 ,即表明最小生成树已经找到;
        //若小于 说明还没找到,还需要继续找
            //找到权重最小的边
            Edge edge = pq.delMin();
            //找到两个顶点
            int v = edge.either();
            int w = edge.other(v);

            //判断两个顶点是否在同一个组中,如果在则不做出处理;如果不在一棵树则合并这两个顶点梭子的树(组)
            if (uf.conn(v, w)) {
                continue; //在同一棵树,则不做操作,继续下一次循环
            } //如果不在同一棵树
            uf.union(v, w); //合并v、w所在的树(组)
            mst.add(edge); //让边edge进入mst最小生成树的边中
        }
    }

    //获取最小生成树中所有的边
    public Queue<Edge> edges(){
        return mst;
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Kruskal算法是一种用于求解最小生成树的贪心算法。在MATLAB中,可以通过以下步骤实现Kruskal算法: 1. 将所有边按照权值从小到大排序。 2. 初始化一个空的集合,用于存储最小生成树的边。 3. 遍历排序后的边,如果当前边的两个端点不在同一个集合中,则将该边加入最小生成树的集合中,并将两个端点合并到同一个集合中。 4. 重复步骤3,直到最小生成树的边数等于节点数减一。 在MATLAB中,可以使用sort函数对边进行排序,使用并查集来实现集合的合并和查找操作。具体实现可以参考以下代码: % Kruskal算法实现 function [MST, cost] = kruskal(G) % G为邻接矩阵表示的图,MST为最小生成树的边集,cost为最小生成树的权值和 n = size(G, 1); % 节点数 edges = []; % 边集 for i = 1:n for j = i+1:n if G(i,j) > % 存在边 edges = [edges; i, j, G(i,j)]; % 添加边 end end end edges = sortrows(edges, 3); % 按照权值排序 parent = 1:n; % 初始化并查集 MST = []; % 初始化最小生成树的边集 cost = ; % 初始化最小生成树的权值和 for i = 1:size(edges,1) u = edges(i,1); v = edges(i,2); w = edges(i,3); pu = find(parent, u); % 查找u所在的集合 pv = find(parent, v); % 查找v所在的集合 if pu ~= pv % u和v不在同一个集合中 MST = [MST; u, v]; % 添加边 cost = cost + w; % 更新权值和 parent(pu) = pv; % 合并集合 end if size(MST,1) == n-1 % 边数达到节点数减一,退出循环 break; end end % 并查集的查找操作 function p = find(parent, x) p = x; while parent(p) ~= p p = parent(p); end % 并查集的合并操作 function parent = union(parent, x, y) px = find(parent, x); py = find(parent, y); parent(px) = py;

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值