最小生成树:Kruskal算法

最小生成树:在连通网的所有生成树中,所有边的代价和最小的生成树,称为最小生成树。

Kruskal算法(加边法)

初始最小生成树边数为0,每迭代一次就选择一条满足条件的最小代价边,加入到最小生成树的边集合里

对给定连通图所有边权值进行排序
对新加入边,进行是否形成回路判断(并查算法)
package com.yue.algorithm.pa01;
import java.util.ArrayList;
public class Kruskal {
	class edge {
		int startVertex;
		int endVertex;
		int weight;// 权值
		public edge(int startVertex,int endVertex,int weight){
			this.startVertex=startVertex;
			this.endVertex=endVertex;
			this.weight=weight;
		}
	}
	public static void main(String[] args) {
		Kruskal y = new Kruskal();
		int n=5;//顶点
		int p=7;//边
		edge[] A=new edge[p];
		A[0]=y.new edge(0, 1, 5);
		A[1]=y.new edge(1, 2, 5);
		A[2]=y.new edge(1, 3, 12);
		A[3]=y.new edge(1, 4, 15);
		A[4]=y.new edge(2, 3, 17);
		A[5]=y.new edge(2, 4, 6);
		A[6]=y.new edge(3, 4, 12);
		y.getMinSpanTree(n, A);
	}
	//n==顶点数
	public ArrayList<edge> getMinSpanTree(int n, edge[] A) {
		ArrayList<edge> rs = new ArrayList<Kruskal.edge>();
		int[] parent = new int[n];
		for (int i=0;i<n;i++) {
			parent[i]=i;//每个顶点的老大都是自己
		}
		//按边的权值排序
		sort(A);
		int startVertex,endVertex;
		int p1,p2;
		for(int i=0;i<A.length;i++) {
			startVertex = A[i].startVertex;
			endVertex = A[i].endVertex;
			p1 = find(parent, startVertex);
			p2 = find(parent, endVertex);
			if(p1!=p2) {
				rs.add(A[i]);
				union(parent, startVertex, endVertex);
			}
			if(rs.size()==n-1) {
				break;
			}
		}
		for (edge ed : rs) {
			System.out.println(ed.startVertex+"---"+ed.endVertex+"---"+ed.weight);
		}
		return rs;
	}
	//并查集
	public void union(int[] parent, int index1, int index2) {
        parent[find(parent, index1)] = find(parent, index2);
    }
	public int find(int[] parent, int index) {
        while (parent[index] != index) {
            parent[index] = parent[parent[index]];
            index = parent[index];
        }
        return index;
    }
	// 2-路归并排序
	public void sort(edge[] A) {
		if (A.length <= 1) return;
		int mid = A.length/2;
		edge[] left = getHalfEdge(A, 0,mid-1);
		edge[] right = getHalfEdge(A, mid,A.length-1);
		sort(left);
		sort(right);
		merge(A,left,right);
	}

	private void merge(edge[] A,edge[] left, edge[] right) {
		int l=0,r=0,index=0;
		while(l<left.length && r<right.length) {
			if(left[l].weight>right[r].weight) {
				A[index++]=right[r++];
			}else {
				A[index++]=left[l++];
			}
		}
		while(l<left.length) {
			A[index++]=left[l++];
		}
		while(r<right.length) {
			A[index++]=right[r++];
		}
	}

	private edge[] getHalfEdge(edge[] A, int s,int e) {
		edge[] rs = new edge[e-s+1];
		for(int i=s;i<=e;i++) {
			rs[i-s]=A[i];
		}
		return rs;
	}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值