import org.eclipse.jetty.util.ArrayQueue; import java.util.HashMap; import java.util.Queue; //图的基本算法 public class Graph { //图邻接矩阵 //节点之间不连通用 65535表示 private static int[][] arcs; //节点数 private static int num; //是否访问过 private static boolean[] hasVisit; //记录访问过的前一个节点 static int pre; public static void main(String[] args) { int[][] arcs = { {0, 65535, 2, 65535, 6}, {9, 0, 3, 65535, 65535}, {65535, 65535, 0, 5, 65535}, {65535, 65535, 65535, 0, 1}, {65535, 65535, 65535, 65535, 0} }; int[][] arcswithnodirction = { {65535, 6, 1, 5, 65535,65535}, {6, 65535, 5, 65535, 3,65535}, {1, 5, 65535, 5, 6,4}, {5, 65535, 5, 65535, 65535,2}, {65535, 3, 6, 65535, 65535,6}, {65535, 65535, 4, 2, 6,65535} }; // Graph graph = new Graph(arcs); // graph.traverse_DFS(0); // graph.traverse_BFS(0); Graph graph = new Graph(arcswithnodirction); // graph.miniSpanTree(); graph.miniSpanTree_kruskal(); } //初始化图 public Graph(int[][] arcs) { this.arcs = arcs; num = arcs.length; } //深度优先遍历, public static void traverse_DFS(int begin) { hasVisit = new boolean[num]; for (int i = 0; i < num; i++) { DFS(i); } } public static void DFS(int begin) { if (hasVisit[begin]) return; System.out.print(begin + ","); hasVisit[begin] = true; for (int i = 0; i < num; i++) { if (!hasVisit[i] && arcs[begin][i] != 65535) { DFS(i); } } } // 广度优先遍历,给出图邻接矩阵和开始遍历的节点 public static void traverse_BFS(int begin) { hasVisit = new boolean[num]; Queue<Integer> bfs=new ArrayQueue<>(); int i=0; while (bfs.size()>0 || i<num) { if (bfs.isEmpty()) { if(!hasVisit[i]) { bfs.add(i); } i++; } else { int t = bfs.poll(); System.out.print(t + ","); hasVisit[t] = true; for (int j = 0; j < num; j++) { if (!hasVisit[j] && arcs[t][j] != 65535) { bfs.add(j); } } } } } //最小生成树,边是无向边:每次取出剩余边中两个端点不同时在以获取的连通中的边 public static void miniSpanTree() { HashMap<Integer,Integer> connected=new HashMap<Integer,Integer>(); //如果节点数小于num就接着查找。 // 找不到不在已经连通的图的点中且不和他们构成环的边就退出(此时图不连通) StringBuilder sb=new StringBuilder(); while (connected.size()<num) { //开始的时候讲第一个节点加入 if (connected.size()==0) { int minfirst=0; for(int i=0;i<num;i++) { minfirst=arcs[0][minfirst]>arcs[0][i]?i:minfirst; } if(arcs[0][minfirst]==65535) { System.out.println("图不是连通的"); return; } connected.put(0,0); connected.put(minfirst,minfirst); sb.append(0+"---->"+minfirst+":"+arcs[0][minfirst]+" "); } else { //查找和connected连接的边的最小值,且这些边不能和connected中的边构成环 int minti=-1,mintj=-1; for(Integer i:connected.keySet()) { int mint=-1; for(int j=0;j<num;j++) { if(connected.get(j)==null ) { if(minti==-1 && mintj==-1) { minti=i; mintj=j; } else if(arcs[minti][mintj]>arcs[i][j]) { minti=i; mintj=j; } } } } if(minti!=-1 && mintj!=-1 && arcs[minti][mintj]!=65535) { connected.put(minti,minti); connected.put(mintj,mintj); sb.append(minti+"---->"+mintj+":"+arcs[minti][mintj]+" "); } else { System.out.println("图不是连通的"); return; } } } if(connected.size()==num) { System.out.println(sb); } } public static void miniSpanTree_kruskal() { int edgenum=0; //获取边数 for(int i=0;i<num;i++) { for(int j=i+1;j<num;j++) if(arcs[i][j]!=65535) edgenum+=1; } node[] edge=new node[edgenum]; int[] vset=new int[edgenum]; //初始化边 int k=0; for(int i=0;i<num;i++) { for(int j=i+1;j<num;j++) if(arcs[i][j]!=65535) { edge[k]=new node(); edge[k].start=i; edge[k].end=j; edge[k].value=arcs[i][j]; k++; } } sort(edge); //初始化边 for(int i=0;i<edgenum;i++) { vset[i]=i; } int tempnum=0; for(int i=0;i<edgenum;i++) { if(tempnum==num-1) { System.out.println("图已经连通"); return; } if(vset[edge[i].start]!=vset[edge[i].end]) { System.out.println(edge[i].start+"-->"+edge[i].end+":"+edge[i].value); vset[edge[i].end]=vset[edge[i].start]; tempnum++; } } if(tempnum!=num-1) System.out.println("图不连通"); } static void sort(node[] nodes) { for(int i=0;i<nodes.length;i++) { int mini=i; for(int j=i;j<nodes.length;j++) { mini=nodes[mini].value>nodes[j].value?j:mini; } //交换节点 node nodetemp=new node(); nodetemp.start=nodes[i].start; nodetemp.end=nodes[i].end; nodetemp.value=nodes[i].value; nodes[i].start=nodes[mini].start; nodes[i].end=nodes[mini].end; nodes[i].value=nodes[mini].value; nodes[mini].start=nodetemp.start; nodes[mini].end=nodetemp.end; nodes[mini].value=nodetemp.value; } } } class node{public int start;public int end;public int value;} ;
图基本算法:深度广度遍历最小生成树
最新推荐文章于 2024-05-13 09:15:00 发布