java编写Prim算法实现最小生成树(LazyPrim算法的优化版)

之前写的"java实现最小生成树问题"是用LazyPrim算法解决的,时间复杂度为O(ElogE),现在用的Prim算法的时间复杂度为O(ElogV)级别。

 PrimMST类中我将之前存储Edge的最小堆换成了存储权值的最小索引堆

类PrimMST

public class PrimMST {
	private SparseGraph sg;   //稀疏图
	private IndexMinHeap imh;   //最小索引堆(保存被标记节点相邻横切边的权值)
	private ArrayList<Edge> edgeTo=new ArrayList<Edge>(); //保存被标记节点相邻横切边
	private boolean marked[];
	private ArrayList<Edge> mst=new ArrayList<Edge>();  //存储最小生成树的Edge
	private int mstWeight;    //最小的权值和
	
	public PrimMST(SparseGraph sg) {
		this.sg = sg;
		imh=new IndexMinHeap(sg.V());  //以图的顶点数为容量
		marked=new boolean[sg.V()];
		for(int i=0;i<sg.V();i++){
			marked[i]=false;
			edgeTo.add(null);
		}
		mst.clear();		
		//Prim算法
		visit(0);
		while(!imh.isEmpty()){
			int v=imh.extractMinIndex();   //取出当前被访问节点的相邻横切边权值中的最小值的Edge索引
			assert(edgeTo.get(v)!=null);   
			mst.add(edgeTo.get(v));        //将这条Edge加入最小生成树
			visit(v);
		}
		mstWeight=mst.get(0).wt();
		for(int i=1;i<mst.size();i++){
			mstWeight+=mst.get(i).wt();
		}
	}

	private void visit(int v){
		assert(!marked[v]);
		marked[v]=true;
		ArrayList<Edge> arr=sg.getGraph(v);
		Iterator<Edge> ite=arr.iterator();
		while(ite.hasNext()){
			Edge e=ite.next();
			int w=e.other(v);
			if(!marked[w]){
				if(edgeTo.get(w)==null){      //判断这条Edge是否已经被加入了edgeTo
					imh.insert(w, e.wt());   //将当前被访问的v点的相邻横切边的权值插入imh   
					edgeTo.set(w, e);        //将当前被访问的v点的相邻横切边加入edgeTo
				}else if(e.wt()<edgeTo.get(w).wt()){   
					imh.set(w, e.wt());    //修改w节点的权值
					edgeTo.set(w, e);      //修改w点的横切边为新值
				}
			}
		}
	}
	
	
	
	public ArrayList<Edge> mstEdges(){
		return mst;
	}
	
	public int result(){
		return mstWeight;
	}
	public static void main(String[] args) {
		int N=20;  //顶点
		int M=200;   //边
		SparseGraph sg=new SparseGraph(N,false);
		for(int i=0;i<M;i++){
			sg.addEdge(new Random().nextInt(N), new Random().nextInt(N),new Random().nextInt(100)+1);//权值[1,101)
		}
		PrimMST la=new PrimMST(sg);
		System.out.println("最小生成树为");
		ArrayList<Edge> arr=la.mstEdges();
		for(int i=0;i<arr.size();i++){
			System.out.println("{"+arr.get(i).v()+"-"+arr.get(i).w()+",wt:"+arr.get(i).wt()+"}");
		}
		System.out.println();
		System.out.println("最小权值和为"+la.result());
	}

}
结果如图:
下面比较一下两种算法的耗时,下面是比较代码:
                int N=20;  //顶点
		int M=200;   //边
		SparseGraph sg=new SparseGraph(N,false);
		for(int i=0;i<M;i++){
			sg.addEdge(new Random().nextInt(N), new Random().nextInt(N),new Random().nextInt(100)+1);//权值[1,101)
		}
		System.out.println("PrimMST耗时:");
		long startTime=System.nanoTime();   //获取开始时间
		PrimMST la=new PrimMST(sg);
		long endTime=System.nanoTime(); //获取结束时间  
		System.out.println("程序运行时间: "+(endTime-startTime)+" 纳秒"); 
		
		System.out.println("LazyPrimMST耗时:");
		long s_startTime=System.nanoTime();   //获取开始时间
		LazyPrimMST lpm=new LazyPrimMST(sg);
		long s_endTime=System.nanoTime(); //获取结束时间  
		System.out.println("程序运行时间: "+(s_endTime-s_startTime)+" 纳秒"); 

比较结果如下图:



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值