图的一些算法比较复杂,这里分多个博客进行总结
图的相关概念
其实之前的几种数据结构,其实比较简单,之前的记忆还比较清晰,但是到图这个地方,有些概念就有些模糊了,这里还是现在总结一下图的相关概念。
定义
定义:图(graph)是由一些点(vertex)和这些点之间的连线(edge)所组成的;其中,点通常被成为"顶点(vertex)",而点与点之间的连线则被成为"边或弧"(edege)。通常记为,G=(V,E)。
根据边是否有方向,可以分为有向图和无向图
无向图
有向图
邻接点和度
邻接点
一条边上的两个顶点叫做邻接点。
例如,上面无向图G0中的顶点A和顶点C就是邻接点。
在有向图中,除了邻接点之外;还有"入边"和"出边"的概念。
顶点的入边,是指以该顶点为终点的边。而顶点的出边,则是指以该顶点为起点的边。
*例如,上面有向图G2中的B和E是邻接点;***是B的出边,还是E的入边。
度
在无向图中,某个顶点的度是邻接到该顶点的边(或弧)的数目。
例如,上面无向图G0中顶点A的度是2。
在有向图中,度还有"入度"和"出度"之分。
某个顶点的入度,是指以该顶点为终点的边的数目。而顶点的出度,则是指以该顶点为起点的边的数目。
顶点的度=入度+出度。
例如,上面有向图G2中,顶点B的入度是2,出度是3;顶点B的度*=2+3=5**。*
图的存储方式
邻接矩阵
邻接矩阵是指用矩阵来表示图。它是采用矩阵来描述图中顶点之间的关系(及弧或边的权)。
假设图中顶点数为n,则邻接矩阵定义为:
通常采用两个数组来实现邻接矩阵:一个一维数组用来保存顶点信息,一个二维数组来用保存边的信息。
邻接矩阵的缺点就是比较耗费空间。
无向图的邻接矩阵
相关代码设计
public class MatrixDG {
int size;
char[] vertexs; //图顶点名称
int[][] matrix; //图关系矩阵
}
具体的构建方法
/**
* autor:liman
* createtime:2020/2/9
* comment: 无向图的数组表示
*/
public class MatrixNDG {
int size;
char[] vertexs; //图顶点名称
int[][] matrix; //图关系矩阵
public MatrixNDG(char[] vertexs, char[][] edges) {
size = vertexs.length;
matrix = new int[size][size];
this.vertexs = vertexs;
for (char[] c : edges) {
int p1 = getPosition(c[0]);
int p2 = getPosition(c[1]);
//无向图,两个对称的位置都需要存储
matrix[p1][p2] = 1;
matrix[p2][p1] = 1;
}
}
public void print() {
for (int[] i : matrix) {
for (int j : i) {
System.out.print(j + " ");
}
System.out.println();
}
}
//根据顶点名称获取对应的矩阵下标
private int getPosition(char ch) {
for (int i = 0; i < vertexs.length; i++) {
if (vertexs[i] == ch) {
return i;
}
}
return -1;
}
public static void main(String[] args) {
char[] vexs = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K'};
char[][] edges = new char[][]{
{'A', 'C'},
{'A', 'D'},
{'A', 'F'},
{'B', 'C'},
{'C', 'D'},
{'E', 'G'},
{'D', 'G'},
{'I', 'J'},
{'J', 'G'},
{'E', 'H'},
{'H', 'K'}};
MatrixNDG matrixNDG = new MatrixNDG(vexs,edges);
matrixNDG.print();
}
}
有向图的邻接矩阵
有向图的构建存储结构与上面一致,只是在构造的时候少一行代码,具体如下:
public MatrixDG(char[] vertexs, char[][] edges) {
size = vertexs.length;
matrix = new int[size][size];
this.vertexs = vertexs;
for (char[] c : edges) {
int p1 = getPosition(c[0]);
int p2 = getPosition(c[1]);
//有向图,只需要存储一个即可
matrix[p1][p2] = 1;
}
}
邻接表
邻接表是图的一种链式存储表示方法。它是改进后的"邻接矩阵",它的缺点是不方便判断两个顶点之间是否有边,但是相对邻接矩阵来说更省空间。
无向图的邻接表
具体的存储设计
/**
* autor:liman
* createtime:2020/2/9
* comment: 邻接表的方式存储无向图
*/
public class ListNDG {
Vertex[] vertexList; //这里就是一个存储节点的数组
int size;
class Vertex{
char ch;
Vertex next;
public Vertex(char ch) {
this.ch = ch;
}
void add(char ch){
Vertex node = this;
while(node.next!=null){//找到链表结尾
node = node.next;
}
node.next = new Vertex(ch);
}
}
}
具体的构建操作如下:
public ListNDG(char[] vertexs,char[][] edgs){
size = vertexs.length;
this.vertexList = new Vertex[size];//确定邻接表的大小
//设置邻接表的每一个节点
for(int i = 0;i<size;i++){
this.vertexList[i] = new Vertex(vertexs[i]);
}
//存储边的信息
for(char[] c:edgs){
int p1 = getPosition(c[0]);
vertexList[p1].add(c[1]);
int p2 = getPosition(c[1]);
vertexList[p2].add(c[0]);
}
}
//根据顶点名称获取链表下标
private int getPosition(char ch){
for(int i =0;i<size;i++){
if(vertexList[i].ch==ch){
return i;
}
}
return -1;
}
public void print(){
for(int i = 0;i<size;i++){
Vertex temp = vertexList[i];
while(temp!=null){
System.out.print(temp.ch+" ");
temp = temp.next;
}
System.out.println();
}
}
public static void main(String[] args) {
char[] vexs = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K'};
char[][] edges = new char[][]{
{'A', 'C'},
{'A', 'D'},
{'A', 'F'},
{'B', 'C'},
{'C', 'D'},
{'E', 'G'},
{'D', 'G'},
{'I', 'J'},
{'J', 'G'},
{'E', 'H'},
{'H', 'K'}};
ListNDG listNDG = new ListNDG(vexs,edges);
listNDG.print();
}
有向图的邻接表
与邻接矩阵的方式一样,与无向图就差两行代码
public ListDG(char[] vertexs, char[][] edgs){
size = vertexs.length;
this.vertexList = new Vertex[size];//确定邻接表的大小
//设置邻接表的每一个节点
for(int i = 0;i<size;i++){
this.vertexList[i] = new Vertex(vertexs[i]);
}
//存储边的信息,这里是有向图只存储单向的连接边信息
for(char[] c:edgs){
int p1 = getPosition(c[0]);
vertexList[p1].add(c[1]);
}
}