比较完整的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;
		}

	}
}



 posted on 2020-04-20 19:49  whiplasher  阅读(178)  评论(0编辑  收藏  举报