Prim算法最小生成树

使用临界矩阵

定义类N

属性中包含起始点和终点以及边的权值

class N{
    int power;
    int s,e;
    public N(int power,int s,int e)
    {
        this.s=s;
        this.e=e;
        this.power=power;
    }
}

定义小根堆

class MinHeap1{
    //存数据
    N[]data;
    //堆的大小
    int heapsize=0;
    //构造函数
    public MinHeap1(int length)
    {
        data=new N[length];

    }
    //添加元素时,我们会加入到最后一个位置,需要进行上浮的操作维护堆

    //添加元素
    public boolean add(N t)
    {
        if(heapsize== data.length)
        {
            data=Arrays.copyOf(data,data.length*2);
        }
        data[++heapsize]=t;
        int now=heapsize;
        while(now>1)
        {
            int next=now/2;
            if(data[now].power>=data[next].power)
                break;
            swap(now,next);
            now=next;
        }
        return true;
    }
    //出堆
    public N poll()
    {
        N res=data[1];
        //将最后一个元素放到开头的位置,进行下沉的操作,维护小根堆的性质
        data[1]=data[heapsize];
        heapsize--;
        int now=1;
        while(now*2<=heapsize)
        {
            int next=2*now;
            if(next+1<heapsize&&data[next+1].power<data[next].power)
                next++;
            if(data[next].power>=data[now].power)
                break;
            swap(next,now);
            now=next;
        }
        return res;
    }
    //交换元素
    public void swap(int i,int j)
    {
        N x=this.data[i];
        data[i]=data[j];
        data[j]=x;
    }
    //判断堆是否为空
    public  boolean isEmpty()
    {
        return heapsize==0;
    }
}

主要代码

 public static void Prim() {
     		//记录经过的点
        List<Integer>res=new ArrayList<>();
    	 //一个存点的集合
        Set<Integer>set=new HashSet<>();
     		//记录经历边的权值
        List<Integer>k=new ArrayList<>();
     		
        Random random=new Random();
     			//java原生优先队列
        //PriorityQueue<N>queue=new PriorityQueue<>((t1,t2)->{return t1.power- t2.power;});
     		//自定义堆
        MinHeap1 queue=new MinHeap1(100);
     		//随机取一个点
        int p=random.nextInt(a.length);
     		//将初始点添加到res中
        res.add(p);
        set.add(p);
     		//优先队列的初始化
        for(int i=0;i<a[p].length;i++)
        {
            //0代表自己max为无穷
            if(a[p][i]!=0&&a[p][i]!=max)
            queue.add(new N(a[p][i],p,i));
        }
     	//要保证set包含每一个点
        while(set.size()<a.length)
        {
            //出队
            N t=queue.poll();
            //如果包含所能到达的目标点证明有回路直接略过
            if(set.contains(t.e)&&set.contains(t.s))
                continue;
            //不包含目标点
            if(!set.contains(t.e))
            {
                
                k.add(t.power);
                //将他加入集合中
                set.add(t.e);
                res.add(t.e);
                //将目标点作为起始点,添加对应能取的目标点
                for(int i=0;i<a[t.e].length;i++)
                {
                    if(a[t.e][i]!=0&&a[t.e][i]!=max)
                    queue.add(new N(a[t.e][i],t.e,i));
                }
            }
        }
        System.out.println("最小生成树为:");
        for(int i:res)
            System.out.print(i+"->");
        System.out.println();
        System.out.println("对应边的值");
        for(int i:k)
        {
            System.out.print(i+" ");
        }
    }

}

测试

//测试 
public final  static  int max=Integer.MAX_VALUE;
    public static int [][]a={
            {0,1,5,6,max,max},
            {1,0,8,max,4,max},
            {5,8,0,7,2,max},
            {6,max,7,0,max,3},
            {max,4,2,max,0,9},
            {max,max,max,3,9,0},
    };


    public static void main(String[] args) {
        Prim();
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值