求最小生成树的Prim算法和Kruskal算法

import java.util.Scanner;

public class Test {
	/*
	 *求最小生成树的prim算法
	 *其中,weight中存储的是图中每条边的代价,如果两点之间不存在边则存储-1。
	 *    lowcost存储的是当前选出的节点到未选中节点的最短距离
	 *    closeset记录了当前最短距离是从哪个被选中的节点产生的
	 *    used记录了节点是否被选出来了,true代表已选中。
	 */
	public static void main(String[] args){
		Scanner reader = new Scanner(System.in);
		int n = reader.nextInt();
		int[][] weight = new int[n+1][n+1];
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n;j++){
				weight[i][j] = reader.nextInt();
			}
		}
		int[] lowcost = new int[n+1];
		int[] closeset = new int[n+1];
		boolean[] used = new boolean[n+1];
		
		used[1] = true;
		for(int i=2;i<=n;i++){
			lowcost[i] = weight[1][i];
			closeset[i] = 1;
		}
		for(int i=2;i<=n;i++){
			int min = Integer.MAX_VALUE;
			int j=1;
			for(int k=2;k<=n;k++){//选择当前已选中节点到未选中节点的所有路径中最小的一条路径
				if(lowcost[k]!=-1&&lowcost[k]<min&&!used[k]){
					min = lowcost[k];
					j = k;
				}
			}
			used[j] = true;
			System.out.println(closeset[j]+"---->"+j+" 路径长为:"+min);//最小路径是从closeset出发的。
			for(int k=2;k<=n;k++){//因为新加入了j节点,所以需要更新lowcost。
				if((weight[j][k]<lowcost[k]||lowcost[k]==-1)&&!used[k]){
					lowcost[k] = weight[j][k];
					closeset[k] = j;
				}
			}
		}
	}
}
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeSet;

public class Test {
	/*
	 *求最小生成树的kruskal算法
	 *算法思想:首先将每条边按照代价从低到高排序,依次选择代价最小的边,
	 *如果这条边的两个顶点不在同一个连通分量,则将该边加入最小生成树中,
	 *直到所有的顶点都在一个连通分量中。
	 */
	public static void main(String[] args){
		GraphInit graph = new GraphInit();
		int[] points = graph.initPoint();
		ArrayList<Edge> edges = graph.initEdge();
		Collections.sort(edges);
		ArrayList<HashSet<Integer>> sets = new ArrayList<>();//记录连通分量
		for(int i=0;i<points.length;i++){//首先初始化,每个顶点都单独在一个连通分量中。
			HashSet<Integer> set = new HashSet<>();
			set.add(points[i]);
			sets.add(set);
		}
		int totalDistance = 0;
		for(Edge edge:edges){//依次检查每条边
			int start = edge.start;
			int end = edge.end;
			int start_index = -1,end_index = -1;
			for(int i=0;i<sets.size();i++){//找到该条边的两个顶点是否在一个连通分量中。
				if(sets.get(i).contains(start))
					start_index = i;
				if(sets.get(i).contains(end))
					end_index = i;
				if(start_index>=0&&end_index>=0)
					break;
			}
			if(start_index!=end_index){//如果不在一个连通分量中,将该条边加入到结果集中,并且将两个连通分量合并成一个连通分量
				System.out.println(edge.toString());
				totalDistance += edge.distance;
				HashSet<Integer> startSet = sets.get(start_index);
				HashSet<Integer> endSet = sets.get(end_index);
				sets.remove(startSet);
				sets.remove(endSet);
				startSet.addAll(endSet);//合并连通分量
				sets.add(startSet);
			}
			if(sets.size()==1){//如果只剩下一个连通分量,结束。
				break;
			}
		}
		System.out.println(totalDistance);
	}
	
}
/*
 * 图的初始化类
 */
class GraphInit{
	public final int pointNums = 5;
	
	public int[] initPoint(){//初始化顶点
		return new int[]{1,2,3,4,5};
	}
	
	public ArrayList<Edge> initEdge(){//初始化边
		ArrayList<Edge> edges = new ArrayList<>();
		edges.add(new Edge(1,2,1));
		edges.add(new Edge(1,3,2));
		edges.add(new Edge(1,4,3));
		edges.add(new Edge(2,3,2));
		edges.add(new Edge(3,4,4));
		edges.add(new Edge(3,5,3));
		edges.add(new Edge(4,5,2));
		return edges;
	}
}
/*
 * 边类
 * 实现了comparable接口
 */
class Edge implements Comparable<Edge>{
	public int start;
	public int end;
	public int distance;
	public Edge(int start,int end,int distance){
		this.start = start;
		this.end = end;
		this.distance = distance;
	}
	@Override
	public String toString(){
		return start+"-->"+end;
	}
	@Override
	public int compareTo(Edge object){
		return this.distance>object.distance?1:(this.distance==object.distance?0:-1);
	}
}

 

转载于:https://my.oschina.net/iterxc/blog/741543

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值