Java実装最小生成ツリーアルゴリズム(Primアルゴリズム)

8195 ワード

Primアルゴリズム
Primアルゴリズムは、成長中のツリーにエッジを追加します.最初はこの木には頂点が1つしかありませんでしたが、V-1のエッジが追加され、次の接続ツリーの頂点とツリーになく重みが最も小さいエッジがツリーに追加されます.
インプリメンテーション
最小生成ツリーの遅延実装
  • 最小生成ツリーのエッジ(横断エッジ)Queue mst
  • を1つのキューで保存
  • 最小優先キューすべてのエッジMinPQ pqを保持最小エッジを削除することによって新しい最小生成ツリーのエッジが得られ、スタックベースの最小優先キューによって
  • が実現される.
  • すべての頂点を保持する配列(頂点がアクセスされているかどうかをマークするために使用され、1つのエッジに2つの頂点があり、2つの頂点がアクセスされていることは、追加されていることを示し、エッジが失効していることを示す)
  • .
    インプリメンテーション:まずvisit()メソッドで頂点をツリーに追加し、アクセス済みとしてマークします.次に、頂点に関連付けられたすべてのエッジを優先キューに追加して、キューにツリー頂点と非ツリー頂点を接続するすべてのエッジが含まれていることを保証します.
    コード内ループ実装:優先キューからエッジを取り出してツリーに追加し、エッジの別の頂点をツリーに追加し、新しい頂点をパラメータとしてvisit()メソッドを呼び出して横断エッジの結合を更新します.すなわち、新しい頂点に関連付けられたエッジを優先キューに追加し、優先キューから重みが最小で失効していないエッジを取り出します.新しい頂点ループ呼び出しを再取得
    public class LazyPrimMST {
    	public boolean[] marked;    //        
    	public Queue mst;     //       
    	public MinPQ pq;      //     (      ) 
    
    	
    	/**
    	 *  v    v-1                  v   ,v        
    	 * @param G
    	 */
    	public LazyPrimMST(EdgeWeightGraph G) {
    		pq = new MinPQ();
    		mst = new LinkedList<>();
    		marked = new boolean[G.V()];
    
    		visit(G, 0);
    		while (!pq.isEmpty()) {
    			Edge e = pq.delMin();
    			System.out.println("      :"+e);
    			int v = e.either(),w = e.other(v);
    			if(marked[v]&&marked[w])
    				continue;                                       //     
    			System.out.println("    :"+e);
    			mst.add(e);                                         //       
    			System.out.println("------------------------------------");
    			if(!marked[v])                                     //                 
    				visit(G,v);
    			if(!marked[w])
    				visit(G,w);
    		}
    	}
    
    	/**
    	 * @param g
    	 * @param i
    	 */
    	private void visit(EdgeWeightGraph g, int v) {
    		//    v          v               
    		marked[v] = true;
    		for(Edge e : g.adj(v)) {
    			if(!marked[e.other(v)])
    				System.out.println("    "+ e);
    				pq.insert(e);
    		}
    	}
    	
    	public Iterable edges(){
    		return mst;
    	}
    }
    

    重み付きエッジのデータ型Edge
    public class Edge implements Comparable{
        public final int v;
        public final int w;
        public final double weight;
        
        public Edge(int v,int w,double weight) {
        	this.v = v;
        	this.w = w;
        	this.weight = weight;
        }
        
        public int either() {
        	return v;
        }
        
        public int other(int vertex) {
        	if(vertex==v)
        		return w;
        	else if(vertex==w)
        		return v;
        	else 
        		throw new RuntimeException("Inconsistent Edge");
        }
        
        public double weight() {
        	return weight;
        }
    
    	/* (non-Javadoc)
    	 * @see java.lang.Object#toString()
    	 */
    	@Override
    	public String toString() {
    		return String.format("%d-%d %.2f", v,w,weight);
    	}
    
    	/* (non-Javadoc)
    	 * @see java.lang.Comparable#compareTo(java.lang.Object)
    	 */
    	@Override
    	public int compareTo(Edge o) {         //  ComparaTo  ,         
    		// TODO Auto-generated method stub
    		if(this.weight()o.weight()) return 1;
    		else return 0;
    	}
        
        
    }
    

    加重無方向図のデータ型
    public class EdgeWeightGraph {
          private final int V;
          private int E;               //   
          private Bag[] adj;     //   
          
          public EdgeWeightGraph(int v) {
        	  this.V = v;
        	  this.E = 0;
        	  adj = new Bag[V];
        	  for(int i = 0;i();
        	  }
          }
          
          public int V() {
        	  return V;
          }
          
          public int E() {
        	  return E;
          }
          
          public void addEdge(Edge e) {
        	  int v = e.either();
        	  int w = e.other(v);
        	  adj[v].add(e);
        	  adj[w].add(e);
        	  E++;
          }
          
          public Iterable adj(int v){
        	  return adj[v];
          }
          
          public Iterable edges(){    //      
        	  Stack s = new Stack();
        	  for(int i = 0;i

    最小優先キュー
    public class MinPQ> {  
    	private Key[] pq;
    	private int N = 0;
    
    	public MinPQ(int initCapacity) {
    		pq = (Key[]) new Comparable[initCapacity + 1];
    	}
    
    	public MinPQ() {
    		this(1);
    	}
    
    	public void insert(Key key) {
    		if (N == pq.length - 1) {
    			resize(2 * pq.length);
    		}
    		N++;
    		pq[N] = key;
    		swim(N);
    	}
    
    	/**
    	 * @param i
    	 */
    	private void resize(int i) {
    		Key[] temp = (Key[]) new Comparable[i];
    		for (int j = 0; j < pq.length; j++) {
    			temp[j] = pq[j];
    		}
    		pq = temp;
    	}
    
    	public Key delMin() {
    		exch(pq, 1, N);
    		Key min = pq[N];
    		pq[N] = null;
    		N--;
    		skin(1);
    		return min;
    	}
    
    	private void swim(int i) {
    		while (i > 1 && greater(i / 2, i)) {
    			exch(i, i / 2);
    			i = i / 2;
    		}
    	}
    
    	private void exch(int i, int j) {
    		Key temp = pq[i];
    		pq[i] = pq[j];
    		pq[j] = temp;
    	}
    
    	/**
    	 * @param i
    	 */
    	private void skin(int i) {
    		while (2 * i <= N) {
    			int k = 2 * i;
    			if (k < N && greater(k, k + 1)) { //            
    				k++;
    			}
    			if (greater(k, i)) { //               
    				break;
    			}
    			exch(pq, i, k);
    			i = k;
    		}
    	}
    
    	private boolean greater(int i, int k) {
    		return pq[i].compareTo(pq[k]) > 0;
    	}
    
    	/**
    	 * @param k
    	 * @param i
    	 */
    	private static void exch(Comparable[] v, int k, int i) {
    		Comparable temp = v[i];
    		v[i] = v[k];
    		v[k] = temp;
    	}
    
    	public static void show(Comparable[] a) {
    		for (int i = 1; i < a.length; i++) {
    			System.out.print(a[i] + " ");
    		}
    		System.out.println();
    	}
    
    	
    	private boolean less(int i, int j) {
    		return pq[i].compareTo(pq[j]) < 0;
    	}
    
    	/**
    	 * @param i
    	 * @param k
    	 * @return
    	 */
    	private static boolean greater(Comparable i, Comparable k) {
    		// TODO Auto-generated method stub
    		System.out.println(i + " " + k);
    		return i.compareTo(k) > 0;
    	}
    
    	public int size() {
    		return N;
    	}
    
    	public boolean isEmpty() {
    		if (N == 0) {
    			return true;
    		}
    		return false;
    	}
    }
    

    テスト
    public class Test {
    	public static void main(String[] args) {
    		EdgeWeightGraph graph = new EdgeWeightGraph(8);
    
    		graph.addEdge(new Edge(4, 5, 0.35));
    		graph.addEdge(new Edge(4, 7, 0.37));
    		graph.addEdge(new Edge(5, 7, 0.28));
    		graph.addEdge(new Edge(0, 7, 0.16));
    		graph.addEdge(new Edge(1, 5, 0.32));
    		graph.addEdge(new Edge(0, 4, 0.38));
    		graph.addEdge(new Edge(2, 3, 0.17));
    		graph.addEdge(new Edge(1, 7, 0.19));
    		graph.addEdge(new Edge(0, 2, 0.26));
    		graph.addEdge(new Edge(1, 2, 0.36));
    		graph.addEdge(new Edge(1, 3, 0.29));
    		graph.addEdge(new Edge(2, 7, 0.34));
    		graph.addEdge(new Edge(6, 2, 0.40));
    		graph.addEdge(new Edge(3, 6, 0.52));
    		graph.addEdge(new Edge(6, 0, 0.58));
    		graph.addEdge(new Edge(6, 4, 0.93));
    
    		LazyPrimMST lpm = new LazyPrimMST(graph);
    		Queue q = new LinkedList();
    		q = (Queue) lpm.edges();
    		System.out.println("     :");
    		for (Edge edge : q) {
    			System.out.println(edge);
    		}
    	}
    }
    
    

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