图的边集是可以转化为邻接矩阵的。
邻接矩阵的定义如下:
邻接矩阵(Adjacency Matrix):是表示顶点之间相邻关系的矩阵。设G=(V,E)是一个图,其中V={v1,v2,…,vn}。G的邻接矩阵是一个具有下列性质的n阶方阵:
①对无向图而言,邻接矩阵一定是对称的,而且对角线一定为零(在此仅讨论无向简单图),有向图则不一定如此。
②在无向图中,任一顶点i的度为第i列所有元素的和,在有向图中顶点i的出度为第i行所有元素的和,而入度为第i列所有元素的和。
③用邻接矩阵法表示图共需要n^2个空间,由于无向图的邻接矩阵一定具有对称关系,所以扣除对角线为零外,仅需要存储上三角形或下三角形的数据即可,因此仅需要n(n-1)/2个空间。
边集就是一个图所有边的集合。
这里使用ArrayList edgeSet一个动态的一维数组表示一个无向图的边集。定义:edgeSet中的顺序为奇数与顺序为偶数的共同表示一条边。如下的测试用例:
ArrayList<Integer> edgeSet = new ArrayList<Integer>(); edgeSet.add(1); edgeSet.add(2); edgeSet.add(1); edgeSet.add(3); edgeSet.add(2); edgeSet.add(3); edgeSet.add(2); edgeSet.add(4);
就是定义存在边集{(1,2),(1,3),(2,3),(2,4)},现在的任务就是把它转化为这个图的邻接矩阵:
1 2
3 4
1 0 1
1 0
2 1 0
1 1
3 1 1
0 0
4 0 1
0 0
这里 横轴1-4与数组组成1-4的矩阵元素坐标,如果得到的结果是1,则表示,图中存在此边。比如矩阵元素中a[1][2]=1,则边集一定存在边(1,2),如果是0,则图中必定不存在这条边。比如a[1][4]=0,那么在边集中一定找不到(1,4)这条边。
邻接矩阵虽然看起来是二维数组,但是这里还是一维数组表示,只是输出的话以如下的方法输出,那么输出的结果就是矩阵了。
//输出以一维数组的表示的矩阵 public static void printAdjacencyMatrix(int adjacencyMatrix[]) { //遍历这个一维数据 for (int i = 0; i < adjacencyMatrix.length; i++) { //每输出一个元素则同时输出一个制表符 System.out.print(adjacencyMatrix[i] + "\t"); //如果遍历的计数器i+1,刚好是矩阵长度的平方,的倍数,则输出一个换行 if (((i + 1) % Math.sqrt(adjacencyMatrix.length)) == 0) { System.out.println(); } } System.out.println(); }
此方法的关键是换行的输出。比如这个的输出矩阵,i从0开始遇到4,8,12,16则输出一个换行,这个矩阵的长度是25,因此便有了如上的“如果遍历的计数器i+1,刚好是矩阵长度的平方,的倍数,则输出一个换行”:
0 1
2 3 4
1 0 1
1 0
2 1 0
1 1
3 1 1
0 0
4 0 1
0 0
要把边集转化成邻接矩阵,首先要以如下的情况初始化邻接矩阵,布置好横轴、纵轴,当然,那个0只是为了占领那个邻接矩阵a[0][0]这个没有意义的位置。
0 1
2 3 4
1 0 0
0 0
2 0 0
0 0
3 0 0
0 0
4 0 0
0 0
此时应该先根据边集求出点集。根据边集求出点集在《【Java】为ArrayList去重》(点击打开链接)已经介绍过了,这里不再赘述,就是一个边集元素去重的过程。
由于邻接矩阵式由一维数组表示的。因此纵轴的位置是 计数器i x 点集长度+1,比如上面的数组,点集就是{1,2,3,4},长度为4,纵轴1,2,3,4分别在一维数组的5,11,16,21这个位置,因此便有了如下的代码:
System.out.println("初始化邻接矩阵:"); ArrayList<Integer> nodeSet = new ArrayList(new HashSet(edgeSet)); int adjacencyMatrix[] = new int[(nodeSet.size() + 1) * (nodeSet.size() + 1)]; for (int i = 0; i <= nodeSet.size(); i++) { if (i == 0) { adjacencyMatrix[i] = 0; } else { adjacencyMatrix[i] = nodeSet.get(i - 1); adjacencyMatrix[i * (nodeSet.size() + 1)] = nodeSet.get(i - 1); } }
接着,是最核心的一步,首先要遍历点集,求出这个点的邻接节点。点的邻接节点根据这个点与边集,如下方法求出:
//求点的邻接节点 public static ArrayList<Integer> neighbourNode(ArrayList<Integer> edgeSet, int node) { //设置一个动态数组ArrayList保存此点的邻接节点 ArrayList<Integer> neighbourNode = new ArrayList<Integer>(); //遍历边集,看那条边拥有此点,那么这条边的另一点,就是此点的邻接节点 for (int i = 0; i < edgeSet.size(); i = i + 2) { if (node == edgeSet.get(i)) { neighbourNode.add(edgeSet.get(i + 1)); } } for (int i = 1; i < edgeSet.size(); i = i + 2) { if (node == edgeSet.get(i)) { neighbourNode.add(edgeSet.get(i - 1)); } } return neighbourNode; }
求出点的邻接节点集之后,就开始遍历这个点的邻接节点集,更新邻接矩阵中的元素。找出这点与其邻接节点,组成的一个矩阵元素坐标,把这个这个矩阵元素坐标所对应的值从0改成1,对所有点求出其邻接节点,之后再该上面的方法,更新邻接矩阵,因此便有了如下的代码:
System.out.println("最终的邻接矩阵:"); for (int i =1; i <= nodeSet.size(); i++) { ArrayList<Integer> neighbourNode=neighbourNode(edgeSet,adjacencyMatrix[i]); for(int j=0;j<neighbourNode.size(); j++){ for(int k=0;k<=nodeSet.size();k++){ if(neighbourNode.get(j)==adjacencyMatrix[k * (nodeSet.size()+1)]){ adjacencyMatrix[(nodeSet.size()+1)*k+i]=1; } } } } printAdjacencyMatrix(adjacencyMatrix);
至此,边集就最终转化成邻接矩阵了。全代码如下:
import java.util.*; public class edgeSet_AdjacencyMatrix { //求点的邻接节点 public static ArrayList<Integer> neighbourNode(ArrayList<Integer> edgeSet, int node) { //设置一个动态数组ArrayList保存此点的邻接节点 ArrayList<Integer> neighbourNode = new ArrayList<Integer>(); //遍历边集,看那条边拥有此点,那么这条边的另一点,就是此点的邻接节点 for (int i = 0; i < edgeSet.size(); i = i + 2) { if (node == edgeSet.get(i)) { neighbourNode.add(edgeSet.get(i + 1)); } } for (int i = 1; i < edgeSet.size(); i = i + 2) { if (node == edgeSet.get(i)) { neighbourNode.add(edgeSet.get(i - 1)); } } return neighbourNode; } //输出以一维数组的表示的矩阵 public static void printAdjacencyMatrix(int adjacencyMatrix[]) { //遍历这个一维数据 for (int i = 0; i < adjacencyMatrix.length; i++) { //每输出一个元素则同时输出一个制表符 System.out.print(adjacencyMatrix[i] + "\t"); //如果遍历的计数器i+1,刚好是矩阵长度的平方,的倍数,则输出一个换行 if (((i + 1) % Math.sqrt(adjacencyMatrix.length)) == 0) { System.out.println(); } } System.out.println(); } public static void edgeSet_AdjacencyMatrix(ArrayList<Integer> edgeSet) { System.out.println("初始化邻接矩阵:"); ArrayList<Integer> nodeSet = new ArrayList(new HashSet(edgeSet)); int adjacencyMatrix[] = new int[(nodeSet.size() + 1) * (nodeSet.size() + 1)]; for (int i = 0; i <= nodeSet.size(); i++) { if (i == 0) { adjacencyMatrix[i] = 0; } else { adjacencyMatrix[i] = nodeSet.get(i - 1); adjacencyMatrix[i * (nodeSet.size() + 1)] = nodeSet.get(i - 1); } } printAdjacencyMatrix(adjacencyMatrix); System.out.println("最终的邻接矩阵:"); for (int i =1; i <= nodeSet.size(); i++) { ArrayList<Integer> neighbourNode=neighbourNode(edgeSet,adjacencyMatrix[i]); for(int j=0;j<neighbourNode.size(); j++){ for(int k=0;k<=nodeSet.size();k++){ if(neighbourNode.get(j)==adjacencyMatrix[k * (nodeSet.size()+1)]){ adjacencyMatrix[(nodeSet.size()+1)*k+i]=1; } } } } printAdjacencyMatrix(adjacencyMatrix); } public static void main(String[] args) { ArrayList<Integer> edgeSet = new ArrayList<Integer>(); edgeSet.add(1); edgeSet.add(2); edgeSet.add(1); edgeSet.add(3); edgeSet.add(2); edgeSet.add(3); edgeSet.add(2); edgeSet.add(4); edgeSet_AdjacencyMatrix(edgeSet); } }
边集{(1,2),(1,3),(2,3),(2,4)}的运行结果: