最小生成树之kruskal算法

kruskal算法描述:
假设连通网N=(V,{E}),则令最小生成树的初始状态为只有n个顶点而无边的非连通图T=(V,{ }),图中每个顶点自成一个连通分量。在E中选择代价最小的边,若该边依附的顶点落在T中不同的连通分量上,则将此边加入到T中,否则舍去此边而选择下一条代价最小的边。以此类推,直至T中所有顶点都在同一连通分量上为止。
kruskal算法描述如下:
在这里插入图片描述

package Kruskal;

/**
 * 克鲁斯卡尔算法
 * @author asus
 */
public class Kruskal {
	private Edge[] edges;	// 按权值从小到大排序后的边数组
	private int edgeSize;	// 边数

	public Kruskal(int edgeSize) {
		this.edgeSize = edgeSize;
		edges = new Edge[edgeSize];
	}

	//定义边的内部类
	class Edge {
		private int begin;
		private int end;
		private int weight;

		public Edge(int begin, int end, int weight) {
			super();
			this.begin = begin;
			this.end = end;
			this.weight = weight;
		}

		public int getBegin() {
			return begin;
		}

		public void setBegin(int begin) {
			this.begin = begin;
		}

		public int getEnd() {
			return end;
		}

		public void setEnd(int end) {
			this.end = end;
		}

		public int getWeight() {
			return weight;
		}

		public void setWeight(int weight) {
			this.weight = weight;
		}

	}
	
	//通过邻接矩阵创建数组
	public Edge[] createEdgeArray(int[][] matrix) {		
		int k = 0;
		for (int i = 0; i < matrix.length; i++) {
			for (int j = i + 1; j < matrix[i].length; j++) {
				int m = matrix[i][j];
				if (matrix[i][j] == Integer.MAX_VALUE)
					continue;
				edges[k] = new Edge(i, j, matrix[i][j]);
				k++;
			}
		}
		for (int i = 0; i < edges.length; i++) {
			for (int j = i + 1; j < edges.length; j++) {
				if (edges[j].weight < edges[i].weight) {
					Edge e = edges[i];
					edges[i] = edges[j];
					edges[j] = e;
				}
			}
		}

		return edges;
	}

	public void miniSpanTreeKruskal() {
		int m, n, sum = 0;
		int[] parent = new int[edgeSize];// 用于验证是否构成回路,角标为某条边的起点,值为该边的终点
		for (int i = 0; i < parent.length; i++) {
			parent[i] = 0;
		}
		for (int i = 0; i < parent.length; i++) {
			m = find(parent, edges[i].begin);// 以edges[i]边的起点为检索起点,找到其可以连接到的最终终点
			n = find(parent, edges[i].end);// 以edges[i]边的终点为检索起点,找到其可以连接到的最终终点
			if (m != n) {// 新加入的edges[i]边不会和已加入的边构成回路
				parent[m] = n;
				System.out.println("连接起点:" + edges[i].begin + ",连接终点:" + edges[i].end + ",权值为:" + edges[i].weight);
				sum += edges[i].weight;
			} else {
				System.out.println("边" + i + "构成了回路");
			}
		}
		System.out.println("sum:" + sum);
	}

	/**
	 * 在图中以node为搜索起点进行检索,最终返回检索到的终点。即表示,从起点node开始,不论以何种路径检索,最终会连接到终点。
	 * 
	 * @param parent 用于检验是否构成回路的数组
	 * @param node   起始顶点,在parent中为角标
	 * @return 返回终点
	 */
	private int find(int[] parent, int node) {
		while (parent[node] > 0) {// 已经添加了边
			node = parent[node];// 以检索到的终点为新的起点继续检索
		}

		return node;
	}
}

时间复杂度为O(eloge),适合于求边稀疏的网的最小生成树。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值