首先要先说明一下其实这种最小生成树问题的作用领域感觉还是比较实际的,意思就是在已知的坐标位置上进行生成最小生成树而这生成树能使得整体的距离之和最小,如果在现实生活中的话就是能够使得已有的位置之间建立的完整道路线最短,相应的费用就最低!!!
1.直接进行贪婪选择说明
如图中所示,一开始先给定了起始点(就是生成树的根),然后将位置记录下来,然后遍历剩下的位置,看看哪些位置在跟位置的附近,然后找出其中权值最小的,记录第二个位置以及相应的权值;(每次都要将位置点放在一个集合中,记该集合为U)然后再比遍历剩下的点中哪些点在已有集合U中位置点附近的,找出权值最小的,再记录下该位置点以及权值,位置点还是要放在集合U中,多次循环直到所有的点全部放到集合U中,就说明生成树已经OK!
算法伪代码:
MST-PRIM(G,w,r)
1. U<-{r}
2. T<-NULL
3. Q<-V-{r}
4. while Q!=NULL
5. do (u,v)<-集合除去U点外剩下的点中在其附近且权值最小
6. T<-T合并(u,v)//记录权值
7. U<-U合并v //记录位置点
8. Q<-Q-v //除去被记录的点
9. return T
JAVA:
Greater.java
package Jamin;
import java.util.Comparator;
public class Greater implements Comparator<Comparable>{
public int compare(Comparable x,Comparable y) {
return x.compareTo(y);
}
}
Less.java
package Jamin;
import java.util.Comparator;
public class Less implements Comparator<Comparable>{
public int compare(Comparable x,Comparable y) {
return y.compareTo(x);
}
}
LinearList.java
package Jamin;
import java.util.*;
public class LinearList {
public static int partition(List<Comparable> a,int p,int r,Comparator comp)//如果要对集合对象或数组对象进行排序,需要实现Comparator接口以达到我们想要的目标。
{
Comparable x;
int i,j;
x=a.get(r);
i=p-1;
for(j=p;j<r;j++)
if(comp.compare(a.get(j), x)<=0) {//如果不符合规则比较则为-1,符合则为1
i++;
Collections.swap(a, i, j);
}
Collections.swap(a, i+1, r);
return i+1;
}
public static void merge(Comparable[] a,int p,int q,int r) {//Comparable为通用数据类型
int i,j,k,
n1=q-p+1,
n2=r-q;
Comparable[] L=Arrays.copyOfRange(a, p, q+1),//将a[p...q]复制到L
R=Arrays.copyOfRange(a, q+1, r+1);//最后一个不复制
i=j=0;
k=p;
while(i<n1&&j<n2) {
if(((Comparable) L[i]).compareTo(R[j])<0) {//比较,当L[i]
a[k]=L[i];
i++;}
else
{a[k]=R[j];
j++;}
k++;
}
if(i<n1)
for(;i<n1;i++)
a[k++]=L[i];
if(j<n2)
for(;j<n2;j++)
a[k++]=R[j];
}
public static int randmizedPartition(List<Comparable> a,int p,int r,Comparator comp) {
int i=p+(int)((double)(r-p)*Math.random());
Collections.swap(a,i,r);
return partition(a,p,r,comp);
}
public static int left(int i) {
return 2*i+1;//由于数组一开始下标为0,所以跟标号为0,再大环境中更改为数组标号
}
public static int right(int i) {
return 2*i+2;
}
public static int parent(int i) {
if(i%2==1)
return i/2;
return i/2-1;
}
public static void heapify(List<Comparable> a,int i,int heapSize,Comparator comp) {
int l=left(i),r=right(i),most;
if((l<heapSize)&&(comp.compare(a.get(l), a.get(i))>0))
most=l;
else
most=i;
if((r<heapSize)&&(comp.compare(a.get(r), a.get(most))>0))
most=r;
if(most!=i) {
Collections.swap(a,i,most);
heapify(a,most,heapSize,comp);
}
}
public static void buildHeap(List<Comparable> a,Comparator comp) {
int heapSize=a.size();
for(int i=heapSize/2;i>=0;i--)
heapify(a,i,heapSize,comp);
}
}
Prioqueue.java
package Jamin;
import java.util.Vector;
import java.util.Comparator;
import java.util.Collections;
public class Prioqueue {
private Vector<Comparable> heap;
private int heapsize;
Comparator comparator;
public Prioqueue() {
heapsize=0;
heap=new Vector<Comparable>();
comparator=new Greater();
}
public Prioqueue(Comparator comp) {
heapsize=0;
heap=new Vector<Comparable>();
comparator=comp;
}
public void enqueue(Comparable e) {
int i=heapsize++;
heap.add(e);
while((i>0)&&(comparator.compare(heap.get(i), heap.get(LinearList.parent(i)))>0)) {
Collections.swap(heap, LinearList.parent(i), i);
i=LinearList.parent(i);
}
}
public Comparable dequeue() {
if(heapsize<1)
return null;
Comparable top=heap.get(0);
heapsize--;
heap.set(0, heap.get(heapsize));
LinearList.heapify(heap, 0, heapsize, comparator);
return top;
}
public boolean empty() {
return heapsize<=0;
}
public void fix() {
int i;
for(i=heapsize/2;i>=0;i--)
LinearList.heapify(heap, i, heapsize, comparator);
}
}
Vertex.java
package Jamin;
public class Vertex implements Comparable<Vertex>{
double weight;
int index;
public Vertex() {}
public Vertex(double w,int i) {
weight=w;
index=i;
}
public int compareTo(Vertex v) {
// TODO Auto-generated method stub
if(weight>v.weight)
return 1;
if(weight<v.weight)
return -1;
return 0;
}
}
MST.java
package Jamin;
import java.util.Arrays;
public class MST {
public static Pair prime(double[][] w,int r) {
int n=w.length,i;
Vertex[] key=new Vertex[n];
int[] pi=new int[n];
boolean[] poped=new boolean[n];
for(i=0;i<n;i++)
key[i]=new Vertex(Double.POSITIVE_INFINITY,i);//POSITIVE_INFINITY表示正无穷
key[r].weight=0.0;
Arrays.fill(pi, -1);
Arrays.fill(poped, false);
Prioqueue Q=new Prioqueue(new Less());
for(i=0;i<n;i++)
Q.enqueue(key[i]);
while(!Q.empty()) {
int u=((Vertex)(Q.dequeue())).index;
poped[u]=true;
for(int v=0;v<n;v++) {
if(w[u][v]>0.0)
if(!poped[v])
if(w[u][v]<key[v].weight) {
pi[v]=u;
key[v].weight=w[u][v];
}
}
Q.fix();
}
return Pair.make(key, pi);
}
}
Test.java
package Jamin;
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
double a[][]= {{0,4,0,0,0,0,0,8,0,},
{4,0,8,0,0,0,0,11,0},
{0,8,9,7,0,4,0,0,2},
{0,0,7,0,9,14,0,0,0},
{0,0,0,9,0,10,0,0,0},
{0,0,4,14,10,0,2,0,0},
{0,0,0,0,0,2,0,1,6},
{8,11,0,0,0,0,1,0,7},
{0,0,2,0,0,0,6,7,0}};//这一坨东西呢就是表示权值啦,
//比如第一个表示a到a的权值,第一行第二个表示a到b的权值
double weight=0.0;
int i,n=9;//n表示总共几个位置点
int[] pi;
Vertex[] key;
Pair r=new Pair();
r=MST.prime(a, 0);
key=(Vertex[])r.first;
pi=(int[])r.second;
for(i=0;i<n;i++) {
weight+=key[i].weight;
if(pi[i]>=0)
System.out.print("<"+pi[i]+","+i+">");
}
System.out.println();
System.out.println("weight:"+weight);
}
}
输出结果:
<0,1><5,2><2,3><3,4><6,5><7,6><0,7><2,8>
weight:37.0