017最小生成树Prim算法即时实现

图学习笔记索引

001自定义输入流In类实现
002背包数据类型Bag实现
003无向图数据类型实现
004基于图的深度优先搜索
005使用深度优先搜索找图中的所有连通分量
005-1基于深度优先搜索查找图中连通路径
006基于深度优先搜索判断图中是否存在环
007基于深度优先搜索判断一个无向图图是否是一个二分图
008广度优先搜索查找连通图中的最短路径
009有向图数据类型实现
010有向图的可达性
011带权重的无向边数据类型Edge实现
012加权无向图数据类型实现
013寻找有向环
014有向图中基于深度优先搜索的顶点排序
015查找、排序、符号表、散列表等算法实现(1)
016最小生成树Prim算法延时实现

本文参考《算法(第4版)》

1.依赖类

从文件中读取图的顶点关系。
tinyEWG.txt中的内容:
8
16
4 5 0.35
4 7 0.37
5 7 0.28
0 7 0.16
1 5 0.32
0 4 0.38
2 3 0.17
1 7 0.19
0 2 0.26
1 2 0.36
1 3 0.29
2 7 0.34
6 2 0.40
3 6 0.52
6 0 0.58
6 4 0.93
点击文字获取:001自定义输入流In类实现
点击文字获取:索引优先队列IndexMinPQ实现
索引优先队列IndexMinPQ实现

package algorithms.rank; 
import java.util.Arrays;
import java.util.Comparator;
 
public class IndexMinPQ<T> {
    private int[] pq;
    private int[] qp;
    private Object[] element;
    private final int capacity;
    private int size;
    private Comparator<? super T> cmp;

    private static class Cmp<T> implements Comparator<T>{
        @SuppressWarnings({ "unchecked", "rawtypes" })
        @Override
        public int compare(T t1, T t2) {
            return ((Comparable)(t1)).compareTo(t2);
        }
    }
     
    private static void swap(int[] a, int i, int j){
        int tmp;
        tmp = a[i];
        a[i] = a[j];
        a[j] = tmp;
    }
     
    //与对象关联的整数范围是[0,capacity-1]
    public IndexMinPQ(int capacity, Comparator<T> cmp){
        this.capacity = capacity;
        pq = new int[capacity+1];
        qp = new int[capacity+1];
        Arrays.fill(qp, -1);  //初始化qp中的每个元素为-1;
        element = new Object[capacity+1];
        if(cmp == null){
            this.cmp = new Cmp<T>();
        }
    }
     
    public void enqueue(int k, T t){
    	//System.out.println("k = " + k);
        k++;//使得关联的整数可以为0 
        if(k > capacity){
            throw new IllegalArgumentException();
        }
         
        if(qp[k] != -1){ //更新
            element[k] = t;
            swim(qp[k]);
            sink(qp[k]);
            return;
        }
          
        pq[++size] = k;
        qp[k] = size;  //k的索引
        element[k] = t;
         
        swim(size);
    }
    
    public int dequeue(){//删除堆顶最小值
        if(size == 0){
            throw new IllegalArgumentException();
        }
        int r = pq[1];
        element[r] = null;
        swap(pq, size, 1);
        swap(qp, pq[size], pq[1]);
        pq[size] = -1;
        size--;
        sink(1); //恢复堆有序
        r--;     //使得关联的整数可以为0
        return r;
    } 
    public void change(int k, T t){
    	//System.out.println("k1 = " + k);
        k++;  //使得关联的整数可以为0
        if(qp[k] == -1){
            throw new IllegalArgumentException();
        }
        element[k] = t;
        swim(qp[k]);
        sink(qp[k]);
    }
     
    public int size(){
        return size;
    }
     
    public boolean isEmpty(){
        return size == 0;
    }
    
    public boolean contains(int v){
    	v++;//使得关联的整数可以为0
    	for(int i = 1; i <= size; i++)
    		if(pq[i] == v)  return true;
    	return false; 
    }
    @SuppressWarnings("unchecked")
    private void swim(int child){
        int parent = child/2;
        while(parent > 0){           
            if(cmp.compare((T)element[pq[child]], (T)element[pq[parent]]) < 0){
                swap(pq, child, parent);
                swap(qp, pq[child], pq[parent]);
                child = parent;
                parent = child/2;
            }else{
                break;
            }
        }
    }

    @SuppressWarnings("unchecked")
    private void sink(int parent){
        int child = parent*2;
        while(child <= size){
            if(child + 1 <= size){
                int r = cmp.compare((T)element[pq[child]], (T)element[pq[child+1]]);
                child = r > 0 ? child+1 : child;
            }
             
            if(cmp.compare((T)element[pq[child]], (T)element[pq[parent]]) < 0){
                swap(pq, parent, child);
                swap(qp, pq[parent], pq[child]);
                parent = child;
                child = parent*2;
            }else{
                break;
            }
        }
    }
     
    
    public static void main(String[] args){
      /*  IndexMinPQ<String> ipq = new IndexMinPQ<String>(11, null);
        ipq.enqueue(0, "k");
        ipq.enqueue(6, "d");
        ipq.enqueue(3, "f");
        ipq.enqueue(4, "c");
        ipq.enqueue(0, "a");
         
        while(!ipq.isEmpty()){
            System.out.println(ipq.dequeue());
        }*/
        
        IndexMinPQ<Double> ipq2 = new IndexMinPQ<Double>(11, null);
        ipq2.enqueue(0, 0.10);
        ipq2.enqueue(6, 0.80);
        ipq2.enqueue(3, 0.76);
        ipq2.enqueue(4, 0.45);
        ipq2.enqueue(5, 0.96);
        System.out.println(ipq2.contains(-1));
        ipq2.change(6, 0.99);
        while(!ipq2.isEmpty()){
            System.out.println(ipq2.dequeue());
        }
        
    }
}

2.最小生成树Prim算法即时实现

package algorithms.graph; 
import java.io.IOException; 
import java.math.BigDecimal;
import algorithms.rank.IndexMinPQ;

//最小生成树Prim算法即时实现
public class PrimMST {
    private Edge[]    edgeTo;
    private double[]  distTo;
    private boolean[] marked;
    private IndexMinPQ<Double> pq;
    public PrimMST(EdgeWeightedGraph G){
    	edgeTo = new Edge[G.V()];
    	marked = new boolean[G.V()];
    	distTo = new double[G.V()];
    	for(int v = 0; v < G.V(); v++)
    	    distTo[v] = Double.POSITIVE_INFINITY;
    	pq = new IndexMinPQ<Double>(G.V()+1,null);
    	
    	distTo[0] = 0.00;
    	pq.enqueue(0, 0.00);
    	while(!pq.isEmpty()){
    		visit(G, pq.dequeue());
    	}
    }
    private void visit(EdgeWeightedGraph G, int v){
    	System.out.println("v="+v);
    	marked[v] = true;
    	for(Edge e : G.adj(v)){
    		int w = e.other(v);
    		if(marked[w]) continue;
    		if(e.weight() < distTo[w]){
    			edgeTo[w] = e;
    			distTo[w] = e.weight(); 
    			if(pq.contains(w))  pq.change(w, distTo[w]);
    			else                pq.enqueue(w, distTo[w]); 
    		}  
    	}
    }
    
    public Edge[] edges(){//去除起始顶点边为空
    	Edge[] temp = new Edge[edgeTo.length-1];
    	for(int i = 1; i < edgeTo.length; i++)
    		temp[i-1] = edgeTo[i];
    	return temp;
    }
    
    public double weight(){
    	double weight = 0.00;
    	for(Edge e : edges())
    		weight += e.weight();
    	BigDecimal bg = new BigDecimal(weight);
  	    weight = bg.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();  
    	return weight;
    }
	public static void main(String[] args) throws IOException {
		 In in = new In("D:\\tinyEWG.txt");  
		 EdgeWeightedGraph EWG = new EdgeWeightedGraph(in);
		 System.out.println(EWG); 
		 PrimMST mst = new PrimMST(EWG);
		 System.out.println("最小生成树中的边:");
		 for(Edge e : mst.edges())
			 System.out.println(e);
		 System.out.println("最小生成树的权重之和:"); 
		 System.out.println(mst.weight());
	}
}

输出:

0 : 0-6 0.58  0-2 0.26  0-4 0.38  0-7 0.16  
1 : 1-3 0.29  1-2 0.36  1-7 0.19  1-5 0.32  
2 : 2-6 0.40  2-7 0.34  2-1 0.36  2-0 0.26  2-3 0.17  
3 : 3-6 0.52  3-1 0.29  3-2 0.17  
4 : 4-6 0.93  4-0 0.38  4-7 0.37  4-5 0.35  
5 : 5-1 0.32  5-7 0.28  5-4 0.35  
6 : 6-4 0.93  6-0 0.58  6-3 0.52  6-2 0.40  
7 : 7-2 0.34  7-1 0.19  7-0 0.16  7-5 0.28  7-4 0.37  

v=0
v=7
v=1
v=2
v=3
v=5
v=4
v=6
最小生成树中的边:
7-1 0.19
0-2 0.26
2-3 0.17
5-4 0.35
7-5 0.28
2-6 0.40
0-7 0.16
最小生成树的权重之和:
1.81

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值