核心思想:利用两个数组分别存储数据元素(顶点)的信息和数据元素之间关系(弧或边)的信息。其中,顶点信息用一维数组表示,关系信息用二维数组表示。
无向图:顶点Vi的度是邻接矩阵中第i(或第i列)的元素之和;
有向图:第i行的元素之和是顶点Vi的出度;第j列的元素之和是顶点Vj的入度;
缺点:存储空间相对而言比较大,n个顶点,n^2个边;
下面给出图的邻接矩阵存储结构的Java实现:
package org.sky.graph;
import java.util.ArrayList;
/**
* @Description 利用邻接矩阵表示无向图(有向图)
* @author sky
* @date 2016/12/27
*/
public class AdjacencyMatrixGragh {
@SuppressWarnings("rawtypes")
private ArrayList vertices = null; //存放顶点
private int[][] edgeMatrix = null; //邻接矩阵
@SuppressWarnings("unused")
private int numEdge = 0; //边数目
private int numVertices = 0; //顶点数目
private int maxWeight = Integer.MAX_VALUE; //两顶点间无通路时,相应边赋值为maxWeight
@SuppressWarnings("rawtypes")
public AdjacencyMatrixGragh(int size){
this.vertices = new ArrayList(size);
this.edgeMatrix = new int[size][size];
for(int i = 0; i < size; i++){ //initialize edgeMatrix
for(int j = 0; j < size; i++){
edgeMatrix[i][j] = (i == j) ? 0 : maxWeight;
}
}
}
/**
* 扩展顶点及邻接矩阵
*/
@SuppressWarnings("unchecked")
public void expand(){
@SuppressWarnings("rawtypes")
ArrayList vLarger = new ArrayList(vertices.size() * 2);
int[][] eLarger = new int[vLarger.size()][vLarger.size()];
for(int i = 0; i < vertices.size(); i++){
vLarger.set(i, vertices.get(i));
for(int j = 0; j < vertices.size(); j++){
eLarger[i][j] = edgeMatrix[i][j];
}
}
vertices = vLarger;
edgeMatrix = eLarger;
}
/**
* 获取顶点v的第一个邻接顶点的位置
* @param v
* @return 存在,返回相应位置;否则,返回-1
*/
public int getFirstNeighbor(int v){
if(v != -1){
for(int col = 0; col < numVertices; col++){
if(edgeMatrix[v][col] > 0 && edgeMatrix[v][col] < maxWeight){
return col;
}
}
}
return -1;
}
/**
* 获取顶点在图中的位置
* @param vertex
* @return 存在,返回相应位置;否则,返回-1
*/
public int getVertexPosition(Object vertex){
for(int i = 0; i < numVertices; i++){
if(vertices.get(i) == vertex){
return i;
}
}
return -1;
}
/**
* 获取位置i处的顶点
* @param i
* @return 存在,返回相应结点信息;否则,返回0
*/
public Object getValue(int i){
return i >= 0 && i < numVertices ? vertices.get(i) : null;
}
/**
*获取边(v1, v2)上的权值
* @param v1
* @param v2
* @return 存在,返回相应边的权值;否则,返回0
*/
public int getWeight(int v1, int v2){
return v1 != -1 && v2 != -1 ? edgeMatrix[v1][v2] : 0;
}
/**
* 在指定两点间添加一条边
* @param start
* @param end
* @param len
*/
public void addEdge(int start, int end, int len){
edgeMatrix[start][end] = len;
edgeMatrix[end][start] = len;
numEdge ++;
}
/**
* 删除指定两点间的一条边
* @param start
* @param end
*/
public void removeEdge(int start, int end){
edgeMatrix[start][end] = 0;
edgeMatrix[end][start] = 0;
numEdge --;
}
/**
* 添加顶点
* @param element
*/
@SuppressWarnings("unchecked")
public void addVertex(Object element){
if(numVertices == vertices.size()){
expand();
}
vertices.set(numVertices ++, element);
}
/**
* 删除顶点。并返回该顶点的值
* @param position
* @return 顶点的值
*/
@SuppressWarnings("unchecked")
public Object removeVertex(int position){
Object result = vertices.get(position);
int size = vertices.size();
for(int i = 0; i < size; i++){ //将关系矩阵向内紧缩
for(int j = 0; j < size; j++){
if(i > position && j > position){
edgeMatrix[i-1][j-1] = edgeMatrix[i][j];
}else if(i > position){
edgeMatrix[i-1][j] = edgeMatrix[i][j];
}else if(j > position){
edgeMatrix[i][j-1] = edgeMatrix[i][j];
}
}
}
for(int i = 0; i <size; i++){ //最后一个顶点紧缩后无意义,赋值为0;
edgeMatrix[size - 1][i] = 0;
edgeMatrix[i][size - 1] = 0;
}
for(int i = position; i < size -1; i++){ //相应调整顶点信息
vertices.set(i, vertices.get(i+1));
}
vertices.set(size-1, null);
numVertices--;
return result;
}
}
参考文献:
图的邻接矩阵实现
图的Java实现(邻接矩阵)