最小生成树-Kruskal和Prim-JAVA代码

1、Kruskal

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;

public class Kruskal {
	
    /** 
     * 求最小树的Kruskal算法 
     * 算法思想:克鲁斯卡尔算法从另一个途径求网中的最小生成树。假设联通网N=(V,{E}),则令最小
     * 生成树的初始状态为只有n个顶点而无边的非连通图T=(V,{}),途中每个顶点自称一个连通分量。 
     * 在E中选择代价最小的边,若该边依附的顶点落在T中不同的连通分量上,则将此边加入到T中,否则舍去此边 
     * 而选择下一条最小的边。以此类推,直至T中所有的顶点都在同一连通分量上为止。 
     * 1 2 3 4 5 6   //初始状态
     * (1 3) 2 4 5 6 //顶点13连通,(1 3)是不是连通分量
     * (1 3) (2 5) 4 6 //25连通
     * (1 2 3 5) 4 6 //35连通,则1 2 3 5整体连通,成为一个连通分量
     * (1 2 3 4 5 6)结束//两顶点若存在同一个连通分量上,则表示存在环,去除此边
     * @param V 图中的节点集合
     * @param E 图中边的集合 
     */  
	public static void KRUSKAL(int [] V,Edge [] E){  
        Arrays.sort(E);//将边按照权重w升序排序  
        ArrayList<HashSet<Integer>> sets=new ArrayList<HashSet<Integer>>();  
        for(int i=0;i<V.length;i++){  
            HashSet<Integer> set=new HashSet<Integer>();  
            set.add(V[i]);  
            sets.add(set);            
        }  
        for(int i=0;i<E.length;i++){  
            int start=E[i].i,end=E[i].j;  
            int counti=-1,countj=-2;  
            for(int j=0;j<sets.size();j++){  
                HashSet<Integer> set=sets.get(j);  
                if(set.contains(start)){  
                    counti=j;  
                }  
                if(set.contains(end)){  
                    countj=j;  
                }  
            }  
            if(counti<0||countj<0) System.err.println("没有在子树中找到节点,错误");  
            if(counti!=countj){  
                System.out.println("输出start="+start+"||end="+end+"||w="+E[i].w);  
                HashSet<Integer> setj=sets.get(countj);  
                sets.remove(countj);  
                HashSet<Integer> seti=sets.get(counti);  
                sets.remove(counti);  
                seti.addAll(setj);  
                sets.add(seti);  
            }else{  
                System.out.println("他们在一棵子树中,不能输出start="+start+"||end="+end+"||w="+E[i].w);  
            }  
        }  
    }  
      
    public static void main(String [] args){  
  
        int [] V={1,2,3,4,5,6};  
        Edge [] E=new Edge[10];  
        E[0]=new Edge(1,2,6);  
        E[1]=new Edge(1,3,1);  
        E[2]=new Edge(1,4,5);  
        E[3]=new Edge(2,3,5);  
        E[4]=new Edge(2,5,3);  
        E[5]=new Edge(3,4,5);  
        E[6]=new Edge(3,5,6);  
        E[7]=new Edge(3,6,4);  
        E[8]=new Edge(4,6,2);  
        E[9]=new Edge(5,6,6);  
        Kruskal.KRUSKAL(V, E);  
    }  
  
}
class Edge implements Comparable<Object> {
	public int i, j, w;

	public Edge(int i, int j, int w) {
		this.i = i;
		this.j = j;
		this.w = w;
	}

	@Override
	public int compareTo(Object o) {
		Edge to = (Edge) o;
		if (this.w > to.w)
			return 1;
		else if (this.w == to.w)
			return 0;
		else
			return -1;

	}

	@Override
	public String toString() {
		return "start=" + i + "||end=" + j + "||w=" + w;
	}
}

2、Prim

import java.util.*;  
public class Prim {  
    static int MAX = Integer.MAX_VALUE;  
  
    public static void main(String[] args) {  
        int[][] map = new int[][] {  
                { 0, 10, MAX, MAX, MAX, 11, MAX, MAX, MAX },  
                { 10, 0, 18, MAX, MAX, MAX, 16, MAX, 12 },  
                { MAX, MAX, 0, 22, MAX, MAX, MAX, MAX, 8 },  
                { MAX, MAX, 22, 0, 20, MAX, MAX, 16, 21 },  
                { MAX, MAX, MAX, 20, 0, 26, MAX, 7, MAX },  
                { 11, MAX, MAX, MAX, 26, 0, 17, MAX, MAX },  
                { MAX, 16, MAX, MAX, MAX, 17, 0, 19, MAX },  
                { MAX, MAX, MAX, 16, 7, MAX, 19, 0, MAX },  
                { MAX, 12, 8, 21, MAX, MAX, MAX, MAX, 0 } };  
        prim(map, map.length);  
    }  
     public static void prim(int[][] graph, int n){  
              
            char[] c = new char[]{'A','B','C','D','E','F','G','E','F'};          
            int[] lowcost = new int[n];  //到新集合的最小权   
            int[] mid= new int[n];//存取前驱结点  
            List<Character> list=new ArrayList<Character>();//用来存储加入结点的顺序
            int i, j, min, minid , sum = 0;  
          //初始化辅助数组
            for(i=1;i<n;i++)  
            {  
                lowcost[i]=graph[0][i];  //初始是以0为起点到各个节点的权重
                mid[i]=0;  //记录每个节点的起点为0
            }  
            list.add(c[0]);  
            //一共需要加入n-1个点
            for(i=1;i<n;i++)  
            {  
                 min=MAX;  
                 minid=0;  
               //每次找到距离集合最近的点
                 for(j=1;j<n;j++)  
                 {  
                     if(lowcost[j]!=0&&lowcost[j]<min)  
                     {  
                         min=lowcost[j];  
                         minid=j;  
                     }  
                 }  
                   
                 if(minid==0) return;  
                 list.add(c[minid]);  
                 lowcost[minid]=0;  
                 sum+=min;  
                 System.out.println(c[mid[minid]] + "到" + c[minid] + " 权值:" + min);
	        	 //加入该点后,更新其它点到集合的距离
                 for(j=1;j<n;j++)  
                 {  
                     if(lowcost[j]!=0&&lowcost[j]>graph[minid][j])  
                     {  
                         lowcost[j]=graph[minid][j];  
                         mid[j]=minid;  
                     }  
                 }  
            }  
            System.out.println("sum:" + sum);  
              
        }  
          
}  

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值