码迷,mamicode.com
首页 > 编程语言 > 详细

【Java】边集转化为邻接矩阵

时间:2015-04-01 17:40:29      阅读:197      评论:0      收藏:0      [点我收藏+]

标签:java   数据结构   边集   图论   邻接矩阵   

图的边集是可以转化为邻接矩阵的。

邻接矩阵的定义如下:

邻接矩阵(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)}的运行结果:

技术分享

【Java】边集转化为邻接矩阵

标签:java   数据结构   边集   图论   邻接矩阵   

原文地址:http://blog.csdn.net/yongh701/article/details/44809383

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!