比较完整的java类写法,
package test1;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.PriorityQueue;
public class Gra {
public static void main(String[] args) {
String[] vertices = { "Seattle", "San Francisco", "Los Angeles", "Denver",
"Kansas City", "Chicago", "Boston", "New York", "Atlanta", "Miami",
"Dallas", "Houston" };
int[][] edges = { { 0, 1, 807 }, { 0, 3, 1331 }, { 0, 5, 2097 },
{ 1, 0, 807 }, { 1, 2, 381 }, { 1, 3, 1267 }, { 2, 1, 381 },
{ 2, 3, 1015 }, { 2, 4, 1663 }, { 2, 10, 1435 }, { 3, 0, 1331 },
{ 3, 1, 1267 }, { 3, 2, 1015 }, { 3, 4, 599 }, { 3, 5, 1003 },
{ 4, 2, 1663 }, { 4, 3, 599 }, { 4, 5, 533 }, { 4, 7, 1260 },
{ 4, 8, 864 }, { 4, 10, 496 }, { 5, 0, 2097 }, { 5, 3, 1003 },
{ 5, 4, 533 }, { 5, 6, 983 }, { 5, 7, 787 }, { 6, 5, 983 },
{ 6, 7, 214 }, { 7, 4, 1260 }, { 7, 5, 787 }, { 7, 6, 214 },
{ 7, 8, 888 }, { 8, 4, 864 }, { 8, 7, 888 }, { 8, 9, 661 },
{ 8, 10, 781 }, { 8, 11, 810 }, { 9, 8, 661 }, { 9, 11, 1187 },
{ 10, 2, 1435 }, { 10, 4, 496 }, { 10, 8, 781 }, { 10, 11, 239 },
{ 11, 8, 810 }, { 11, 9, 1187 }, { 11, 10, 239 } };
WeightedGraph<String> graph1 = new WeightedGraph<>(edges, vertices);
WeightedGraph<String>.MST tree=graph1.minSpanningTree(graph1.getIndex("Seattle"));
System.out.println(tree.totalWeight);
WeightedGraph<String> graph2 = new WeightedGraph<>(edges, vertices);
WeightedGraph<String>.MST tree2=graph1.Kruscal(graph1.getIndex("Seattle"));
System.out.println(tree2.totalWeight);
edges = new int[][] { { 0, 1, 2 }, { 0, 3, 8 }, { 1, 0, 2 }, { 1, 2, 7 },
{ 1, 3, 3 }, { 2, 1, 7 }, { 2, 3, 4 }, { 2, 4, 5 }, { 3, 0, 8 },
{ 3, 1, 3 }, { 3, 2, 4 }, { 3, 4, 6 }, { 4, 2, 5 }, { 4, 3, 6 } };
Integer[] vertices1={0,1,2,3,4};
WeightedGraph<Integer> graph3 = new WeightedGraph<Integer>(edges,vertices1 );
WeightedGraph<Integer>.ShortestPathTree tree3 = graph3.getSPT(3);
System.out.println("\n");
int res[]=tree3.cost;
System.out.println(Arrays.toString(res));
}
public interface Graph<V>{
public V getVertex(int index);
public int getDegree(int index);
public int getIndex(V v);
public void printEdges();
public int getSize();
public boolean addVertex(V v);
public boolean addEdge(int u,int v);
public List<Integer> getNeighbors(int index);
}
public static class WeightedEdge implements Comparable<WeightedEdge>{
int u;
int v;
int weight;
public WeightedEdge(int u,int v,int weight) {
this.u=u;
this.v=v;
this.weight=weight;
}
@Override
public int compareTo(WeightedEdge o) {
// TODO Auto-generated method stub
if(this.weight>o.weight) return 1;
if(this.weight<o.weight) return -1;
return 0;
}
}
public static class WeightedGraph<V> implements Graph<V>{
protected List<V> vertices=new ArrayList<>();
public List<PriorityQueue<WeightedEdge>> edges=new ArrayList<>();
public WeightedGraph(int[][] edges,V[] vertices) {
// TODO Auto-generated constructor stub
for(int i=0;i<vertices.length;i++){
this.vertices.add(vertices[i]);
this.edges.add(new PriorityQueue<WeightedEdge>());
}
for(int i=0;i<edges.length;i++){
int u=edges[i][0];
WeightedEdge e=new WeightedEdge(edges[i][0],edges[i][1],edges[i][2]);
this.edges.get(u).add(e);
}
}
public class Tree{
private int parents[];
private int root;
private List<Integer> searchOrder;
public int[] getParents() {
return parents;
}
public int getRoot() {
return root;
}
public List<Integer> getSearchOrder() {
return searchOrder;
}
public Tree(int[] parents, int root, List<Integer> searchOrder) {
super();
this.parents = parents;
this.root = root;
this.searchOrder = searchOrder;
}
}
public Tree BFS(int index){
int[] parents=new int[vertices.size()];
for(int i=0;i<parents.length;i++){
parents[i]=-1;
}
boolean[] isVisited=new boolean[vertices.size()];
List<Integer> searchOrder=new ArrayList<>();
List<Integer> queue=new ArrayList<>();
queue.add(index);
while(!queue.isEmpty()){//队列实现广度优先遍历
int u=queue.remove(0);
isVisited[u]=true;
searchOrder.add(u);
for(WeightedEdge edge:edges.get(u)){
if(!isVisited[edge.v]) {
parents[edge.v]=u;
queue.add(edge.v);
}
}
}
return new Tree(parents, index, searchOrder);
}
public Tree dfs(int index){
int[] parents=new int[vertices.size()];
for(int i=0;i<parents.length;i++){
parents[i]=-1;
}
boolean[] isVisited=new boolean[vertices.size()];
List<Integer> searchOrder=new ArrayList<>();
dfs(index,parents,isVisited,searchOrder);
return new Tree(parents, index, searchOrder);
}
public void dfs(int index,int[] parents,boolean[] isVisited,List<Integer> searchOrder){
isVisited[index]=true;
searchOrder.add(index);
for(WeightedEdge e:this.edges.get(index)){
if(!isVisited[e.v]){
parents[e.v]=index;
dfs(e.v, parents, isVisited, searchOrder);
}
}
}
public class MST extends Tree{
int totalWeight;
public MST(int[] parents, int root, List<Integer> searchOrder,int totalWeight) {
super(parents, root, searchOrder);
this.totalWeight=totalWeight;
// TODO Auto-generated constructor stub
}
}
public MST minSpanningTree(){
return minSpanningTree(0);
}
public MST minT(int index){
List<Integer> minTree=new ArrayList<>();
minTree.add(index);
int totalWeight=0;
int[] parent = new int[vertices.size()]; // Parent of a vertex
for (int i = 0; i < parent.length; i++)
parent[i] = -1;
List<PriorityQueue<WeightedEdge>> edges = deepClone(this.edges); //important
while(minTree.size()<vertices.size()){
int vertexToAdd=-1;
int minWeight=Integer.MAX_VALUE;
for(int i:minTree){
while(!edges.get(i).isEmpty()&&minTree.contains(edges.get(i).peek().v)){
edges.get(i).remove();
}
if(!edges.get(i).isEmpty()&&edges.get(i).peek().weight<minWeight){
minWeight=edges.get(i).peek().weight;
vertexToAdd=edges.get(i).peek().v;
parent[edges.get(i).peek().v]=i;
}
}
if(vertexToAdd!=-1){ //掉掉掉掉掉掉掉掉掉掉掉
minTree.add(vertexToAdd);
totalWeight+=minWeight;
}
else break; //不连通
}
return new MST(parent, index, minTree, totalWeight);
}
public MST minSpanningTree(int index){
List<Integer> minTree=new ArrayList<>();
minTree.add(index);
int totalWeight=0;
int[] parent = new int[vertices.size()]; // Parent of a vertex
for (int i = 0; i < parent.length; i++)
parent[i] = -1;
List<PriorityQueue<WeightedEdge>> edges = deepClone(this.edges); //important
while(minTree.size()<vertices.size()){
int vertexToAdd=-1;
int minWeight=Integer.MAX_VALUE; //每次循环都必须初始化
for(int i:minTree){
while(!edges.get(i).isEmpty()&&minTree.contains(edges.get(i).peek().v))
edges.get(i).remove();
if(!edges.get(i).isEmpty()){
if(edges.get(i).peek().weight<minWeight){
minWeight=edges.get(i).peek().weight;
vertexToAdd=edges.get(i).peek().v;
parent[vertexToAdd]=i;
}
}
}
if(vertexToAdd!=-1){
minTree.add(vertexToAdd);
totalWeight+=minWeight;
}else break;
}
return new MST(parent, index, minTree, totalWeight);
}
public MST Kruscal(int index){
int[] parents=new int[vertices.size()];
for(int i=0;i<parents.length;i++){
parents[i]=i;
}
PriorityQueue<WeightedEdge> pEdges=new PriorityQueue<>();
for(int i=0;i<vertices.size();i++){
pEdges.addAll(edges.get(i));
}
List<Integer> minTree=new ArrayList<>();
int totalWeight=0;
int edgesNumber=0;
while(edgesNumber<vertices.size()-1&&pEdges.size()>0){ //&&后面的防止不连通图一直循环
int u=pEdges.peek().u;
int v=pEdges.peek().v;
int weight=pEdges.remove().weight;
if(getAncestor(parents, u)!=getAncestor(parents, v)){
if(!minTree.contains(u)) minTree.add(u);
if(!minTree.contains(v)) minTree.add(v);
union(u, v, parents);
totalWeight+=weight;
edgesNumber++; //// 最小生成树边数比点数少1即可!!!!!!!!!!
}
}
if(edgesNumber<vertices.size()-1) totalWeight=-1; //不连通
// while(edgesNumber<vertices.size()-1){
// int begin=pEdges.peek().u;
// int end=pEdges.peek().v;
// int weight=pEdges.remove().weight;
// if(getAncestor(parents, begin)!=getAncestor(parents, end)){
// if(!minTree.contains(begin)) minTree.add(begin);
// if(!minTree.contains(end)) minTree.add(end);
// totalWeight+=weight;
// union(begin, end, parents);
// }
// }
return new MST(parents, index, minTree, totalWeight);
}
public void union(int u,int v,int[] parents){
int x=getAncestor(parents, u);
int y=getAncestor(parents, v);
parents[x]=y;
}
public int getAncestor(int[] parents,int index){
while(parents[index]!=index) index=parents[index];
return index;
}
public List<PriorityQueue<WeightedEdge>> deepClone(List<PriorityQueue<WeightedEdge>> edges){
List<PriorityQueue<WeightedEdge>> copyEdges=new ArrayList<>();
for(int i=0;i<edges.size();i++){
copyEdges.add(new PriorityQueue<WeightedEdge>());
for(WeightedEdge edge:edges.get(i)){
copyEdges.get(i).add(edge);
}
}
return copyEdges;
}
//单源最短路径
public class ShortestPathTree extends Tree{
private int[] cost; // cost[v] is the cost from v to source
/** Construct a path */
public ShortestPathTree(int source, int[] parent,
List<Integer> searchOrder, int[] cost) {
super(parent, source, searchOrder);
this.cost = cost;
}
/** Return the cost for a path from the root to vertex v */
public double getCost(int v) {
return cost[v];
}
}
public ShortestPathTree getSPT(int index){
List<Integer> SPTVexs=new ArrayList<>();
SPTVexs.add(index);
int[] parent = new int[vertices.size()];
parent[index] = -1; // The parent of source is set to -1
int[] cost=new int[vertices.size()];
for(int i=0;i<cost.length;i++){
cost[i]=Integer.MAX_VALUE;
}
cost[index]=0;
List<PriorityQueue<WeightedEdge>> edges = deepClone(this.edges); //!!!!!!!!!!!!
while(SPTVexs.size()<vertices.size()){
int minWeight=Integer.MAX_VALUE;
int vertexToAdd=-1;
for(int i:SPTVexs){
while(!edges.get(i).isEmpty()&&SPTVexs.contains(edges.get(i).peek().v)){
edges.get(i).remove();
}
if(!edges.get(i).isEmpty()){
int v=edges.get(i).peek().v;
int weight=edges.get(i).peek().weight; //i -> v
// if(cost[v]>cost[i]+weight) { 每次加入一个最短的边的点
if(minWeight>cost[i]+weight) {
minWeight=weight+cost[i];
parent[v]=i;//////////////////
vertexToAdd=v;
}
}
}//end for
if(vertexToAdd!=-1){
SPTVexs.add(vertexToAdd);
cost[vertexToAdd]=minWeight;
}
else {
break; // 不连通
}
}
return new ShortestPathTree(index, parent, SPTVexs, cost);
}
@Override
public V getVertex(int index) {
// TODO Auto-generated method stub
return vertices.get(index);
}
@Override
public int getDegree(int index) {
// TODO Auto-generated method stub
return 0;
}
@Override
public int getIndex(V v) {
// TODO Auto-generated method stub
return vertices.indexOf(v);
}
@Override
public void printEdges() {
// TODO Auto-generated method stub
}
@Override
public int getSize() {
// TODO Auto-generated method stub
return 0;
}
@Override
public boolean addVertex(V v) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean addEdge(int u, int v) {
// TODO Auto-generated method stub
return false;
}
@Override
public List<Integer> getNeighbors(int index) {
// TODO Auto-generated method stub
return null;
}
}
}