Kruskal算法的JAVA实现

1.算法描述

克鲁斯卡尔算法需要对图的边进行访问,所以克鲁斯卡尔算法的时间复杂度只和边又关系,可以证明其时间复杂度为O(eloge)。

2.算法思想

1.将图各边按照权值进行排序

2.将图遍历一次,找出权值最小的边,(条件:此次找出的边不能和已加入最小生成树集合的边构成环),若符合条件,则加入最小生成树的集合中。不符合条件则继续遍历图,寻找下一个最小权值的边。

3.递归重复步骤1,直到找出n-1条边为止(设图有n个结点,则最小生成树的边数应为n-1条),算法结束。得到的就是此图的最小生成树。


3.JAVA代码

1)结构体定义
// 边的结构体
class ENode {
	char start; // 边的起点
	char end; // 边的终点
	int weight; // 边的权重

	public ENode(char start, char end, int weight) {
		this.start = start;
		this.end = end;
		this.weight = weight;
	}
};

// 邻接表中表的顶点
class VNode {
	char data; // 顶点信息
	ENode firstEdge; // 指向第一条依附该顶点的弧
};

class Graph {
	private static final int INF = Integer.MAX_VALUE; // 最大值

	char[] vertexs; // 顶点集合
	int[][] matrix; // 邻接矩阵

	// 得到当前有向图中的所有边信息
	public List<ENode> getEdges() {
		List<ENode> edges = new ArrayList<ENode>();
		for (int i = 0; i < vertexs.length; i++) {
			for (int j = 0; j < vertexs.length; j++) {
				if (matrix[i][j] != INF) {
					ENode edge = new ENode(vertexs[i], vertexs[j], matrix[i][j]);
					edges.add(edge);
				}
			}
		}

		return edges;
	}
}
2)kruskal算法
	private static final int INF = Integer.MAX_VALUE; // 最大值

	static void qSort(List<ENode> edges, int low, int high) {
		if (low < high) {
			int i = low, j = high;
			ENode edge = edges.get(low);
			while (i < j) {
				while (edge.weight < edges.get(j).weight && i < j)
					j--;
				edges.set(i, edges.get(j));
				while (edge.weight > edges.get(i).weight && i < j)
					i++;
				edges.set(j, edges.get(j));
			}
			edges.set(i, edge);
			qSort(edges, low, i - 1);
			qSort(edges, i + 1, high);
		}
	}

	public static void kruskal(Graph G) {
		// 1.拿到有向图中所有边
		List<ENode> edges = G.getEdges();
		int edgeNum = edges.size();

		// 2.对所有有向边进行排序
		qSort(edges, 0, edgeNum - 1);
		
		ENode[] minTree = new ENode[G.vertexs.length - 1]; // 结果数组,保存kruskal最小生成树的边
		int index = 0; // minTree数组的索引
	
		// 用于保存"已有最小生成树"中每个顶点(以数组下标表示) 与 其经过“最短边”的邻接顶点 (以对应下标的值表示)的并查集
		int[] start2end = new int[G.vertexs.length]; 


		// 3.依次将最短且不与T构成回路的边加入T集合
		for (int i = 0; i < edgeNum; i++) {
			//得到当前最短边 在有向图G中的起始顶点与终结顶点的 下标
			int p1 = getIndex(G, edges.get(i).start); // 获取第i条边的"起点"的序号
			int p2 = getIndex(G, edges.get(i).end); // 获取第i条边的"终点"的序号
			
			//分别得到在T集合中沿当前最短边的“起点”与“终点”遍历到的最后节点,
			//若加入当前最短边后T集合存在回路,则“起点”与“终点”遍历到的最后节点一定是同一节点
	        int m = getEnd(start2end, p1);                 // 获取p1在"已有的最小生成树"中的终点
	        int n = getEnd(start2end, p2);                 // 获取p2在"已有的最小生成树"中的终点
	        
	        //当前最短边加入T集合后没有有回路 则将当前最短边加入T集合,并且记录当前最短边的“起点”与“终点”
	        if (m != n) {
	        	start2end[m] = n;               // “起点”即vends的数组下标与“终点”即vends的对应下标的值
	            minTree[index++] = edges.get(i);           // 保存结果
	        }
		}

	}

	static int getIndex(Graph G, char ch) {
		int i = 0;
		for (; i < G.vertexs.length; i++)
			if (G.vertexs[i] == ch)
				return i;
		return -1;
	}

	static int getEnd(int start2end[], int i) {
		while (start2end[i] != 0)
			i = start2end[i];
		return i;
	}




  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值