最小生成树之prim算法java代码

 思路:1.初始化带权值的图,把相应的点存到一个队列V中.

    2.再创建一个用于储存最小生成树结点的队列U,
            然后先从起始结点V中取一个放进最小生成树结点U中.

        3.通过遍历U中结点来选择这些边加入到优先考虑的边

    集合中,不构成圈且权值最小的边添加到最小生成树中,且把相应      边的另一端加入到U中.

      4. 直到完成最小生成图.

Edge类:

/**
 * 带权重的边的数据类型
 * @interface 
 * @author sanjun
 * @Time 2017-05-02
 */
public class Edge implements Comparable<Edge>{
	 private String begin; //顶点之一
	 private String end;   //另一个顶点
	 private double weight; //边的权重
	   
	   public Edge(String begin, String end, double weight) {
		    this.begin = begin;
			this.end = end;
			this.weight = weight;
	   }
		
		public String getBegin() {
			return begin;
		}
		
		public void setBegin(String begin) {
			this.begin = begin;
		}
		
		public String getEnd() {
			return end;
		}
		
		public void setEnd(String end) {
			this.end = end;
		}
		
		public double getWeight() {
			return weight;
		}
		
		public void setWeight(int weight) {
			this.weight = weight;
		}
		
		public void show(){
			System.out.println(this.getWeight());
		}
		
		/**
		 * 将边进行比较后通过Arrays.sort(Object[] args0)排列
		 * @author sanjun
		 * @param that
		 */
		public int compareTo(Edge that){
			if(this.getWeight() < that.getWeight()) return -1;
			else if(this.getWeight() > that.getWeight()) return +1;
			else return 0;
		}
}

PrimMST类:

import java.util.ArrayList;

/**
 *   @author sanjun
 *   @Time 2017-5-2
 */
public class PrimMST {
	
	private int vertexNum; //结点数目
	private ArrayList<String> U = new ArrayList<String>(); //最小生成树结点
	private ArrayList<Edge> TE = new ArrayList<Edge>(); //最小生成树边
	private ArrayList<String> V = new ArrayList<String>(); //初始结点
	private ArrayList<Edge> E = new ArrayList<Edge>(); //初始边
	
	/**
	 * 初始化图
	 * @author sanjun
	 * @return 
	 */
	private void initGraph(){
		
		vertexNum = 8; //初始化结点数

		for(int i = 0;i < vertexNum ;i++){ //将结点名称放进队列V中
			V.add(i+"");
		}
		
		Edge[] e = {new Edge("4","5",0.35),new Edge("4","7",0.37),
				new Edge("5","7",0.28),new Edge("0","7",0.16),
				new Edge("1","5",0.32),new Edge("0","4",0.38),
				new Edge("2","3",0.17),new Edge("1","7",0.19),
				new Edge("0","2",0.26),new Edge("1","2",0.36),
				new Edge("1","3",0.29),new Edge("2","7",0.34),
				new Edge("6","2",0.40),new Edge("3","6",0.52),
				new Edge("6","0",0.58),new Edge("6","4",0.93)}; //带权值的边
		
		//把边存储入E
		for(int i = 0;i < e.length;i++){
			E.add(e[i]);
		}	
	}
	
	/**
	 * 	首先,创建一个ArrayList用于存放优先考虑的边,
	 *  然后先从起始结点V中取一个放进最小生成树结点U中,
	 *  通过遍历U中结点来选择不构成圈且权值最小的边,
	 *  直到完成最小生成图.
	 *  
	 *	@return 
	 */
	private void createMST() {
		
		ArrayList<Edge> priorEdges = new ArrayList<Edge>(); //优先边集合
		
		U.add(V.get(0)); //取一个结点
		
		for(int i = 0;i < U.size();i++){ //遍历最小生成树结点
			
			String v = U.get(i); //选中结点
			
			//选取与v相关联的边,加入优先边集合
			for(int j = 0;j < E.size();j++){
				
				Edge e = E.get(j); //选中的边
				
				//如果边e的端点存在v,即进入下一个条件
				if(e.getBegin().equals(v)||e.getEnd().equals(v)){
					
					//如果TE中不存在e且e不构成圈,即把e添加到priorEdges中
					if(!TE.contains(e)&&!isCircle(e)){
						
						priorEdges.add(e); //把相关边添加到priorEdges
					}
				}
			}
			
			/**
			 *	删除两端结点都存在U中的边
			 *	原因是:上边条件所限制的边可能在下一个添加相应的
			 *	结点到U中,导致原本存在priorEdges中的边失效(形成圈),故删除 
			 */
			for(int j = 0;j < priorEdges.size();j++){	
				
				if(isCircle(priorEdges.get(j))){ //如果形成圈,即删除该边
					priorEdges.remove(j);        
				}
			}
			
			//对priorEdge里面的边选最小权值的边
			//边按权值从小到大排
			int minIndex = 0; //最小下标
			Edge minEdge = priorEdges.get(minIndex);
			for(int j = 1;j < priorEdges.size();j++){
				//如果priorEdges.get(j)比minEdge小
				if(priorEdges.get(j).compareTo(minEdge) < 0){
					minIndex = j;
					minEdge = priorEdges.get(j);
				}
			}
			
			
			//在priorEdges中取权值最小的边
			Edge edge = priorEdges.get(minIndex);

			TE.add(edge);	//把edge添加到TE中
			
			//由于该边的一端必定在U中,所以把其中一端加入U中
			if(U.contains(edge.getBegin())){
				U.add(edge.getEnd());
			}else{
				U.add(edge.getBegin());
			}
			
			priorEdges.remove(minIndex); //从中删除该边
			
			if(TE.size() == vertexNum - 1){
				break;
			}
		}

		
		//输出最小生成树
		double sum = 0;
		for(int i = 0;i < TE.size();i++){
			Edge edge = TE.get(i);
			sum += edge.getWeight();
			System.out.println(edge.getBegin()+"->"+edge.getEnd()+" 权值:"+edge.getWeight());
		}
		System.out.println("总权值:"+sum);
	}
	
	//判断是否成圈
	private boolean isCircle(Edge edge) {
		if(U.contains(edge.getBegin())&&U.contains(edge.getEnd())){
			return true;
		}else{
			return false;
		}
	}
	
	public static void main(String[]args){
		
		PrimMST primMST = new PrimMST();
		primMST.initGraph();
		primMST.createMST();
		
	}
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
程序 = 数据结构 + 算法  程序是为了解决实际问题而存在的。然而为了解决问题,必定会使用到某些数据结构以及设计一个解决这种数据结构的算法。如果说各种编程语言是程序员的招式,那么数据结构和算法就相当于程序员的内功。编程实战算法,不是念PPT,我们讲的就是实战与代码实现与企业应用。程序 = 数据结构 + 算法                ——图灵奖得主,计算机科学家N.Wirth(沃斯)作为程序员,我们做机器学习也好,做python开发也好,java开发也好。有一种对所有程序员无一例外的刚需 —— 算法与数据结构日常增删改查 + 粘贴复制 + 搜索引擎可以实现很多东西。同样,这样也是没有任何竞争力的。我们只可以粘贴复制相似度极高的功能,稍复杂的逻辑没有任何办法。语言有很多,开发框架更是日新月异3个月不学就落后我们可以学习很多语言,很多框架,但招聘不会考你用5种语言10种框架实现同一个功能。真正让程序员有区分度,企业招聘万年不变的重点 —— 算法与数据结构。算法代表程序员水平的珠穆朗玛。如果说各种编程语言是程序员的招式,那么数据结构和算法就相当于程序员的内功。 想写出精炼、优秀的代码,不通过不断的锤炼,是很难做到的。 开这个系列的目的是为了自我不断积累。不积跬步无以至千里嘛。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值