贪心策略
度量标准: 选择能使迄今为止所计入的边的成本和有最小增加的那条边。
Prim: 逐渐连通,每次选择已加入集合的点中权值最小的边。
Kruskal: 选取边集合中两个边端点都未或有一方未加入结果集合的权值最小的边。
Prim
- 构造邻接矩阵
package Greed;
import java.io.*;
import java.util.*;
public class AdjMatrix {
int[][] edges;//存储边的数组
List<String> vertexList;//储存点的链表
int numOfEdges;//边的数目
public AdjMatrix(int n){
//初始化
edges=new int[n][n];
vertexList=new ArrayList<String>(n);
numOfEdges=0;
}
//得到节点个数
public int getNumOfVertex() {
return vertexList.size();
}
//得到边的条数
public int getNumOfEdges() {
return numOfEdges;
}
//返回节点i的数据
public String getValueByIndex(int i) {
return vertexList.get(i);
}
//返回节点之间的v1,v2权值
public int getWeight(int v1,int v2) {
return edges[v1][v2];
}
//插入节点
public void insertVertex(String v) {
vertexList.add(v);
}
//插入边
public void insertEdges(int v1,int v2,int weight) {
edges[v1][v2]=weight;
edges[v2][v1]=weight;
numOfEdges++;
}
//删除边
public boolean delete(int v1,int v2) {
edges[v1][v2]=0;
numOfEdges--;
if(edges[v1][v2]==0) {
return true;
}else
return false;
}
}
- prim最小生成树函数
package Greed;
import java.util.*;
public class Prim {
int[][] graph;
List<Integer> path=new ArrayList<Integer>();
int min=100000;
int currentMin=0;
int currentVertex;
List<String> vertexList=new ArrayList<String>();
public Prim(int graph[][],List<String> vertexList) {
this.graph=graph;
this.vertexList=vertexList;
path.add(0);
prim();
}
public void prim() {
int count=0;
//while(count<graph.length) {
for(int i=0;i<path.size()&&i<graph.length;i++) {
for(int j=0;j<graph.length;j++) {//遍历path中所有结点中权值最小的
//System.out.print(j+" "+graph[i][j]+" ");
if(graph[path.get(i)][j]!=0&&isNotContain(j)&&min>graph[path.get(i)][j]) {
min=graph[path.get(i)][j];
currentVertex=j;
//System.out.println(min+" min");
}
}
if(min!=10000) {
path.add(currentVertex);
currentMin+=min;
}
min=10000;
}
//count++
//}
for(int i=0;i<path.size();i++) {
System.out.print("路径:"+path.get(i)+" ");
}
System.out.println();
System.out.println("总路程:"+currentMin);
}
public boolean isNotContain(int j) {
boolean flag=true;
for(int i=0;i<path.size();i++) {
if(path.get(i)==j) {
flag=false;
break;
}
}
//System.out.println(j+" "+flag);
return flag;
}
}
- 主函数调用
package Greed;
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
//建立图、邻接矩阵
int n=4,e=4;
AdjMatrix graph=new AdjMatrix(4);
graph.insertVertex("A");
graph.insertVertex("B");
graph.insertVertex("C");
graph.insertVertex("D");
graph.insertEdges(0, 1, 2);
graph.insertEdges(0, 2, 5);
graph.insertEdges(2, 3, 8);
graph.insertEdges(3, 0, 7);
graph.insertEdges(1, 3, 3);
//最小生成树算法
Prim p=new Prim(graph.edges,graph.vertexList);
}
}
kruskal
package algorithm;
import java.util.*;
public class Kruskal {
public Kruskal(AdjMatrix graph) {
int n =graph.getNumOfVertex();//获得节点的数目
//初始化边集合
List<List<Integer>> edges=new ArrayList<List<Integer>>();
for(int i=0;i<n;i++) {
for(int j=i+1;j<n;j++) {
if(graph.edges[i][j]!=0) {
List<Integer> l=new ArrayList<Integer>();
l.add(i);
l.add(j);
l.add(graph.edges[i][j]);
edges.add(l);
}
}
}
System.out.println(n);
//优先队列
PriorityQueue<List<Integer>> queue=new PriorityQueue<List<Integer>>(new Comparator<List<Integer>>() {
@Override
public int compare(List<Integer> o1, List<Integer>o2) {
// TODO Auto-generated method stub
return o1.get(2)-o2.get(2);
}
});
for(int i=0;i<edges.size();i++) {
queue.add(edges.get(i));
}
int[] u= new int[n];
for(int i=0;i<n;i++) {
u[i]=i;
}
int used=0;
while(used<n-1&&!queue.isEmpty()) {
List<Integer> poll = queue.poll();
//判断是否符合要求
boolean checked = checked(u,poll.get(0),poll.get(1));
if(checked==true) {
//输出;
System.out.println(poll);
//将改变
u[poll.get(1)]=poll.get(0);
used++;
}
}
}
private boolean checked(int[] u,int i,int j) {
while(u[i]!=i) {
i=u[i];
}
while(u[j]!=j) {
i=u[j];
}
if(i==j)
return false;
return true;
}
}