1、分别定义图的邻接矩阵和邻接表存储结构;
2、分别在两种存储结构下根据输入的顶点和边(或弧)创建图;
3、分别在两种存储结构下实现求顶点度的操作;
4、分别在两种存储结构下实现图的深度和广度优先遍历算法;
5、实现图的邻接矩阵和邻接表存储结构的转换。
IGraph.java
package experiment3; public interface IGraph { void createGraph(); int getVexNum(); int getArcNum(); Object getVex(int v)throws Exception; int locateVex(Object vex); int firstAdjVex(int v)throws Exception; int nextAdjVex(int v,int w)throws Exception; }
ALGraph.java
package experiment3; import java.util.Scanner; import static experiment3.GraphKind.DG; //邻接表 public class ALGraph implements IGraph { private GraphKind kind; private int vexNum,arcNum; private VNode[]vexs; public ALGraph(){ this(null,0,0,null); } public ALGraph(GraphKind kind, int vexNum, int arcNum, VNode[]vexs){ this.kind=kind; this.vexNum=vexNum; this.arcNum=arcNum; this.vexs=vexs; } public void createGraph(){ Scanner scanner=new Scanner(System.in); System.out.println("请输入图的类型:"); GraphKind kind=GraphKind.valueOf(scanner.next()); switch (kind){ case DG: createDG(); break; case UDG: createUDG(); break; } } public void createDG(){ Scanner scanner=new Scanner(System.in); System.out.println("请分别输入图的顶点数、图的边数:"); vexNum=scanner.nextInt(); arcNum=scanner.nextInt(); vexs=new VNode[vexNum]; System.out.println("请分别输入图的各顶点:"); for (int v=0;v<vexNum;v++) vexs[v]=new VNode(scanner.next()); System.out.println("请输入各边的两个顶点:"); for (int k=0;k<arcNum;k++){ int v=locateVex(scanner.next()); int u=locateVex(scanner.next()); addArc(v,u,1); } } public void createUDG(){ Scanner scanner=new Scanner(System.in); System.out.println("请分别输入图的顶点数、图的边数:"); vexNum=scanner.nextInt(); arcNum=scanner.nextInt(); vexs=new VNode[vexNum]; System.out.println("请分别输入图的各顶点:"); for (int v=0;v<vexNum;v++) vexs[v]=new VNode(scanner.next()); System.out.println("请输入各边的两个顶点:"); for (int k=0;k<arcNum;k++){ int v=locateVex(scanner.next()); int u=locateVex(scanner.next()); addArc(v,u,1); addArc(u,v,1); } } public void addArc(int v,int u,int value){ ArcNode arc=new ArcNode(u,value); arc.nextArc=vexs[v].firstArc; vexs[v].firstArc=arc; } @Override public int getArcNum() { return arcNum; } @Override public int getVexNum() { return vexNum; } public int locateVex(Object vex) { for (int v=0;v<vexNum;v++) { if (vexs[v].data.equals(vex)) return v; } return -1; } public VNode[] getVexs() { return vexs; } public GraphKind getKind() { return kind; } @Override public Object getVex(int v) throws Exception { if (v<0||v>=vexNum) throw new Exception("第"+v+"个顶点不存在"); return vexs[v].getData(); } @Override public int firstAdjVex(int v) throws Exception { if (v<0||v>=vexNum) throw new Exception("第"+v+"个顶点不存在"); VNode vex=vexs[v]; if(vex.firstArc!=null) return vex.firstArc.adjVex; else return -1; } @Override public int nextAdjVex(int v, int w) throws Exception { if (v<0||v>=vexNum) throw new Exception("第"+v+"个顶点不存在"); VNode vex=vexs[v]; ArcNode arcNode=null; for (ArcNode arcNode1=vex.firstArc;arcNode1!=null;arcNode1=arcNode1.nextArc) if (arcNode1.adjVex==w){ arcNode=arcNode1; break; } if (arcNode!=null&&arcNode.nextArc!=null) return arcNode.nextArc.adjVex; else return -1; } public int[]findInDegree(ALGraph G)throws Exception{ int[]indegree=new int[G.getVexNum()]; for (int i=0;i<G.getVexNum();i++) for (ArcNode arcNode=G.getVexs()[i].firstArc;arcNode!=null;arcNode=arcNode.nextArc) ++indegree[arcNode.adjVex]; return indegree; } public int[]findOutDegree(ALGraph G)throws Exception{ int []outdegree=new int[G.getVexNum()]; for (int i=0;i<G.getVexNum();i++) for (ArcNode arcNode=G.getVexs()[i].firstArc;arcNode!=null;arcNode=arcNode.nextArc) ++outdegree[i]; return outdegree; } public void Degree(ALGraph G)throws Exception{ int []indegree=G.findInDegree(G); int []outdegree=G.findOutDegree(G); int []degree=new int[G.getVexNum()]; for (int i=0;i<G.getVexNum();i++) { degree[i] = indegree[i] + outdegree[i]; System.out.println("第"+i+"号顶点的度"+degree[i]); } } public MGraph exchange(ALGraph G)throws Exception{ Object vexs[]=new Object[G.getVexNum()]; int arcs[][]=new int[G.getVexNum()][G.getVexNum()]; for (int i=0;i<G.getVexNum();i++){ vexs[i]=G.getVex(i); } for (int i=0;i<G.getVexNum();i++) for (int j=0;j<G.getVexNum();j++) arcs[i][j]=0; for (int i=0;i<G.getVexNum();i++){ ArcNode arcNode=G.vexs[i].firstArc; while (arcNode!=null){ arcs[i][arcNode.adjVex]=1; arcNode=arcNode.nextArc; } } MGraph mGraph=new MGraph(DG,G.getVexNum(),G.getArcNum(),vexs,arcs); return mGraph; } public void printlist(ALGraph G){ for (int i=0;i<G.getVexNum();i++) { System.out.print(vexs[i].data); ArcNode p=vexs[i].firstArc; while (p!=null) { int m=p.adjVex+1; System.out.print("v"+m); p=p.nextArc; } System.out.println(); } } }
ArcNode.java
package experiment3; //图的邻接表存储表示中的边结点类 public class ArcNode { public int adjVex;//该弧所指向的顶点的位置 public int value;//边的权值 public ArcNode nextArc;//指向的下一条弧; public ArcNode() { this(-1,0,null); } public ArcNode(int adjVex){ this(adjVex,0,null); } public ArcNode(int adjVex,int value){ this(adjVex,value,null); } public ArcNode(int adjVex,int value,ArcNode nextArc){ this.adjVex=adjVex; this.value=value; this.nextArc=nextArc; } }
BFSTraverse.java
package experiment3; import homework.LinkQueue; //广度优先遍历 public class BFSTraverse { private static boolean[]visited; public static void BFSTraverse(IGraph G)throws Exception{ visited=new boolean[G.getVexNum()]; for (int v=0;v<G.getVexNum();v++) visited[v]=false; for (int v=0;v<G.getVexNum();v++) if (!visited[v]) BFS(G,v); } private static void BFS(IGraph G,int v)throws Exception{ visited[v]=true; System.out.print(G.getVex(v).toString()+" "); LinkQueue Q=new LinkQueue(); Q.offer(v); while (!Q.isEmpty()){ int u=(Integer)Q.poll(); for (int w=G.firstAdjVex(u);w>=0;w=G.nextAdjVex(u,w)) if (!visited[w]){ visited[w]=true; System.out.print(G.getVex(w).toString()+" "); Q.offer(w); } } } }
DTraverser.java
package experiment3; //深度优先遍历 public class DTraverser { private static boolean[]visited; public static void DFSTraverse(IGraph G)throws Exception{ visited=new boolean[G.getVexNum()]; for (int v=0;v<G.getVexNum();v++) visited[v]=false; for (int v=0;v<G.getVexNum();v++) if (!visited[v]) DFS(G,v); } public static void DFS(IGraph G,int v)throws Exception{ visited[v]=true; System.out.print(G.getVex(v).toString()+" "); for (int w=G.firstAdjVex(v);w>=0;w=G.nextAdjVex(v,w)) if (!visited[w]) DFS(G,w); } }
GraphKind.java
package experiment3; public enum GraphKind { UDG, DG, }
MGraph.java
package experiment3; import java.util.Scanner; import java.util.Stack; //邻接矩阵 public class MGraph implements IGraph{ public final static int start=0; private GraphKind kind; private int vexNum,arcNum; private Object[]vexs; private int[][]arcs; private static boolean[]visited; public MGraph(){ this(null,0,0,null,null); } public MGraph(GraphKind kind,int vexNum,int arcNum,Object[]vexs,int[][]arcs){ this.kind=kind; this.vexNum=vexNum; this.arcNum=arcNum; this.vexs=vexs; this.arcs=arcs; } @Override public void createGraph() { Scanner sc = new Scanner(System.in); System.out.println("请输入图的类型:"); GraphKind kind = GraphKind.valueOf(sc.next()); switch (kind) { case UDG: createUDG(); return; case DG: createDG(); return; } } public void createUDG(){ Scanner scanner=new Scanner(System.in); System.out.println("请分别输入图的顶点数、图的边数:"); vexNum=scanner.nextInt(); arcNum=scanner.nextInt(); vexs=new Object[vexNum]; System.out.println("请分别输入图的各个顶点:"); for (int v=0;v<vexNum;v++) vexs[v]=scanner.next(); arcs=new int[vexNum][vexNum]; for (int v=0;v<vexNum;v++) for (int u=0;u<vexNum;u++) arcs[v][u]=start; System.out.println("请输入各个边的两个顶点:"); for (int k=0;k<arcNum;k++){ int v=locateVex(scanner.next()); int u=locateVex(scanner.next()); arcs[v][u]=arcs[u][v]=1; } } public void createDG(){ Scanner scanner=new Scanner(System.in); System.out.println("请分别输入图的顶点数、图的边数:"); vexNum=scanner.nextInt(); arcNum=scanner.nextInt(); vexs=new Object[vexNum]; System.out.println("请分别输入图的各个顶点:"); for (int v=0;v<vexNum;v++) vexs[v]=scanner.next(); arcs=new int[vexNum][vexNum]; for (int v=0;v<vexNum;v++) for (int u=0;u<vexNum;u++) arcs[v][u]=start; System.out.println("请输入各个边的两个顶点:"); for (int k=0;k<arcNum;k++){ int v=locateVex(scanner.next()); int u=locateVex(scanner.next()); arcs[v][u]=1; } } //返回顶点数 @Override public int getVexNum() { return vexNum; } //返回边数 @Override public int getArcNum() { return arcNum; } //定位顶点vex在图中的位置 @Override public int locateVex(Object vex) { for (int v=0;v<vexNum;v++) if (vexs[v].equals(vex)) return v; return -1; } //返回v表示结点的值 public Object getVex(int v)throws Exception{ if (v<0||v>=vexNum) throw new Exception("第"+v+"个顶点不存在"); return vexs[v]; } @Override public int firstAdjVex(int v) throws Exception{ if (v<0||v>=vexNum) throw new Exception("第"+v+"个顶点不存在"); for (int j=0;j<vexNum;j++) if (arcs[v][j]==1) return j; return -1; } @Override public int nextAdjVex(int v, int w) throws Exception { if (v<0||v>=vexNum) throw new Exception("第"+v+"个顶点不存在"); for (int j=w+1;j<vexNum;j++) if (arcs[v][j]==1) return j; return -1; } public GraphKind getKind() { return kind; } public int[][] getArcs() { return arcs; } public Object[] getVexs() { return vexs; } //作业 public void DirectedGraph(IGraph G) throws Exception{ //初始化节点遍历的数组 visited=new boolean[G.getVexNum()]; for (int i = 0; i <G.getVexNum(); i++) { visited[i] = false; } //定义存储遍历节点的栈 Stack<Integer> s = new Stack(); for (int i = 0; i < G.getVexNum(); i++) { if (!visited[i]) { //未访问的节点入栈 s.add(i); visited[i] = true; while (!s.isEmpty()) { //出栈 int j = s.pop(); System.out.print(G.getVex(j).toString() + " "); for (int k = G.firstAdjVex(j); k >= 0; k = G.nextAdjVex(j, k)) { if (!visited[k]) s.add(k); visited[k] = true; } } } } } public int[]findInDegree(MGraph G)throws Exception{ int[]indegree=new int[G.getVexNum()]; for (int i=0;i<G.getVexNum();i++) for (int j=0;j<G.getVexNum();j++) if (arcs[j][i]!=0) indegree[i]++; return indegree; } public int[]findOutDegree(MGraph G)throws Exception{ int []outdegree=new int[G.getVexNum()]; for (int i=0;i<G.getVexNum();i++) for (int j=0;j<G.getVexNum();j++) if (arcs[i][j]!=0) outdegree[i]++; return outdegree; } public void Degree(MGraph G)throws Exception{ int[]indegree=G.findInDegree(G); int[]outdegree=G.findOutDegree(G); int[]degree=new int[G.getVexNum()]; for (int i=0;i<G.getVexNum();i++){ degree[i]=indegree[i]+outdegree[i]; System.out.println("第"+i+"号顶点的度"+degree[i]); } } public ALGraph exchange(MGraph G)throws Exception{ VNode[]Vexs=new VNode[G.vexNum]; for (int m=0;m<G.vexNum;m++) { Vexs[m]=new VNode(G.vexs[m]); for (int n = 0; n < G.vexNum; n++) { if (arcs[m][n] == 1){ ArcNode arcNode=new ArcNode(n); G.Head(arcNode,Vexs[m]); } } } ALGraph alGraph=new ALGraph(GraphKind.DG,G.vexNum,G.arcNum,Vexs); return alGraph; } public void Head(ArcNode n,VNode vNode){ ArcNode p; p=vNode.firstArc; vNode.firstArc = n; n.nextArc = p; } public void printlist(MGraph G){ for (int i=0;i<G.vexNum;i++) { for (int j = 0; j < G.vexNum; j++) { System.out.print(arcs[i][j] + " "); } System.out.println(); } } }
VNode.java
package experiment3; //图的邻接表存储表示中的顶点结点类 public class VNode { public Object data;//顶点信息 public ArcNode firstArc;//指向第一条依附于该顶点的弧 public VNode(Object data){ this(data,null); } public VNode(Object data,ArcNode firstArc){ this.data=data; this.firstArc=firstArc; } public Object getData() { return data; } public void setData(Object data) { this.data = data; } public ArcNode getFirstArc() { return firstArc; } public void setFirstArc(ArcNode firstArc) { this.firstArc = firstArc; } }
TestALGraph.java
package experiment3; import java.util.Scanner; public class TestALGraph { //邻接表测试 public static void main(String[] args) throws Exception{ /*ArcNode v12=new ArcNode(1); VNode v1=new VNode("v1",v12); ArcNode v23=new ArcNode(2); ArcNode v24=new ArcNode(3,0,v23); VNode v2=new VNode("v2",v24); ArcNode v34=new ArcNode(3); VNode v3=new VNode("v3",v34); VNode v4=new VNode("v4"); VNode []vexs={v1,v2,v3,v4}; ALGraph alGraph=new ALGraph(GraphKind.DG,4,4,vexs); alGraph.Degree(alGraph); DTraverser dTraverser=new DTraverser(); System.out.print("邻接表的深度优先遍历:"); dTraverser.DFSTraverse(alGraph); BFSTraverse bfsTraverse=new BFSTraverse(); System.out.print("邻接表的广度优先遍历:"); bfsTraverse.BFSTraverse(alGraph); System.out.println(); alGraph.printlist(alGraph); MGraph mGraph=alGraph.exchange(alGraph); System.out.println(); mGraph.Degree(mGraph); System.out.print("转化成邻接矩阵的深度优先遍历:"); dTraverser.DFSTraverse(mGraph); System.out.print("转化成邻接矩阵的广度优先遍历:"); bfsTraverse.BFSTraverse(mGraph); System.out.println(); mGraph.printlist(mGraph);*/ ALGraph alGraph=new ALGraph(); Scanner scanner=new Scanner(System.in); alGraph.createDG(); /*System.out.println("请输入v:(0<=v):"); int v1=scanner.nextInt(); System.out.println("v"+(v1+1)+"的第一个邻接点:"+"v"+(alGraph.firstAdjVex(v1)+1)); System.out.println("请输入v和w,中间以空格分开(0<=v,w<vexNum):"); int v2=scanner.nextInt(); int w=scanner.nextInt(); int a=alGraph.nextAdjVex(v2,w); //v2+1,w+1,a+1为的是和v1,v2,v3,v4相对应。 if (a==-1){ System.out.println("v"+(v2+1)+"相对于"+"v"+(w+1)+"没有下一个邻接点"); }else { System.out.println("v" + (v2 + 1) + "相对于" + "v" + (w+1) + "的下一个邻接点" + "v" + (a+1)); } alGraph.Degree(alGraph);*/ DTraverser dTraverser=new DTraverser(); System.out.print("邻接表的深度优先遍历:"); dTraverser.DFSTraverse(alGraph); BFSTraverse bfsTraverse=new BFSTraverse(); System.out.print("邻接表的广度优先遍历:"); bfsTraverse.BFSTraverse(alGraph); System.out.println(); /*alGraph.printlist(alGraph); MGraph mGraph=alGraph.exchange(alGraph); System.out.println(); mGraph.Degree(mGraph); System.out.print("转化成邻接矩阵的深度优先遍历:"); dTraverser.DFSTraverse(mGraph); System.out.print("转化成邻接矩阵的广度优先遍历:"); bfsTraverse.BFSTraverse(mGraph); System.out.println(); mGraph.printlist(mGraph);*/ } }
TestMGraph.java
package experiment3; import java.util.Scanner; public class TestMGraph { //邻接矩阵测试 public static void main(String[] args) throws Exception{ /*Object vexs[]={"v1","v2","v3","v4"}; int [][]arcs={{0,1,0,0},{0,0,1,1},{0,0,0,1},{0,0,0,0}}; MGraph mGraph=new MGraph(GraphKind.DG,4,4,vexs,arcs); mGraph.Degree(mGraph); DTraverser dTraverser=new DTraverser(); System.out.print("邻接表的深度优先遍历:"); dTraverser.DFSTraverse(mGraph); BFSTraverse bfsTraverse=new BFSTraverse(); System.out.print("邻接表的广度优先遍历:"); bfsTraverse.BFSTraverse(mGraph); System.out.println(); mGraph.printlist(mGraph); ALGraph alGraph=mGraph.exchange(mGraph); System.out.println(); alGraph.Degree(alGraph); System.out.print("转化成邻接矩阵的深度优先遍历:"); dTraverser.DFSTraverse(alGraph); System.out.print("转化成邻接矩阵的广度优先遍历:"); bfsTraverse.BFSTraverse(alGraph); System.out.println(); alGraph.printlist(alGraph);*/ MGraph mGraph=new MGraph(); Scanner scanner=new Scanner(System.in); mGraph.createDG(); System.out.println("请输入v:(0<=v):"); int v1=scanner.nextInt(); System.out.println("v"+(v1+1)+"的第一个邻接点:"+"v"+(mGraph.firstAdjVex(v1)+1)); System.out.println("请输入v和w,中间以空格分开(0<=v,w<vexNum):"); int v2=scanner.nextInt(); int w=scanner.nextInt(); int a=mGraph.nextAdjVex(v2,w); //v2+1,w+1,a+1为的是和v1,v2,v3,v4相对应。 if (a==-1){ System.out.println("v"+(v2+1)+"相对于"+"v"+(w+1)+"没有下一个邻接点"); }else { System.out.println("v" + (v2 + 1) + "相对于" + "v" + (w+1) + "的下一个邻接点" + "v" + (a+1)); } mGraph.Degree(mGraph); DTraverser dTraverser=new DTraverser(); System.out.print("邻接表的深度优先遍历:"); dTraverser.DFSTraverse(mGraph); BFSTraverse bfsTraverse=new BFSTraverse(); System.out.print("邻接表的广度优先遍历:"); bfsTraverse.BFSTraverse(mGraph); System.out.println(); mGraph.printlist(mGraph); ALGraph alGraph=mGraph.exchange(mGraph); System.out.println(); alGraph.Degree(alGraph); System.out.print("转化成邻接矩阵的深度优先遍历:"); dTraverser.DFSTraverse(alGraph); System.out.print("转化成邻接矩阵的广度优先遍历:"); bfsTraverse.BFSTraverse(alGraph); System.out.println(); alGraph.printlist(alGraph); } }