为什么要有图
前面我们学了线性表和树
线性表局限于一个直接前驱和一个直接后继的关系
树也只能有一个直接前驱也就是父节点
当我们需要表示多对多的关系时, 这里我们就用到了图
图的举例说明
图是一种数据结构,其中结点可以具有零个或多个相邻元素。两个结点之间的连接称为边。 结点也可以称为顶点。如图:
图
顶点(vertex) 边(edge) 路径 无向图(下图)
无向图: 顶点之间的连接没有方向,比如A-B,
即可以是 A-> B 也可以 B->A .
路径: 比如从 D -> C 的路径有
- D->B->C
- D->A->B->C
有向图
有向图: 顶点之间的连接有方向,比如A-B,
只能是 A-> B 不能是 B->A .
带权图
带权图:这种边带权值的图也叫网.
图的表示方式有两种:二维数组表示(邻接矩阵);链表表示(邻接表)
邻接矩阵
邻接矩阵是表示图形中顶点之间相邻关系的矩阵,对于n个顶点的图而言,矩阵是的row和col表示的是1....n个点。
邻接表
邻接矩阵需要为每个顶点都分配n个边的空间,其实有很多边都是不存在,会造成空间的一定损失.
邻接表的实现只关心存在的边,不关心不存在的边。因此没有空间浪费,邻接表由数组+链表组成
说明:
标号为0的结点的相关联的结点为 1 2 3 4
标号为1的结点的相关联结点为0 4,
标号为2的结点相关联的结点为 0 4 5
图的案例
要求: 代码实现如下图结构.
思路分析 (1) 存储顶点String 使用 ArrayList (2) 保存矩阵 int[][] edges
A B C D E
A 0 1 1 0 0
B 1 0 1 1 1
C 1 1 0 0 0
D 0 1 0 0 0
E 0 1 0 0 0
//说明
//(1) 1 表示能够直接连接
//(2) 0 表示不能直接连接
代码实现
package cn.icanci.datastructure.graph;
import com.sun.org.apache.bcel.internal.generic.RETURN;
import java.util.ArrayList;
import java.util.Arrays;
/**
* @Author: icanci
* @ProjectName: AlgorithmAndDataStructure
* @PackageName: cn.icanci.datastructure.graph
* @Date: Created in 2020/3/17 8:57
* @ClassAction: 图
*/
public class Graph {
//存储顶点集合
private ArrayList vertexList;
//存储对应的邻接矩阵
private int[][] edges;
//表示边的数目
private int numOfEdges;
public static void main(String[] args) {
//测试图
//节点的个数
int n = 5;
String vertexValue[] = {"A", "B", "C", "D", "E"};
//创建图对象
Graph graph = new Graph(n);
//循环添加节点
for (String value : vertexValue) {
graph.insertVertex(value);
}
//添加边
graph.insertEdge(0,1,1);
graph.insertEdge(0,2,1);
graph.insertEdge(1,2,1);
graph.insertEdge(1,3,1);
graph.insertEdge(1,4,1);
//显示
graph.showGraph();
}
/**
* 构造器
*
* @param n
*/
public Graph(int n) {
//初始化矩阵和 vertexList
edges = new int[n][n];
vertexList = new ArrayList<>(n);
this.numOfEdges = 0;
}
//图中常用的方法
public int getNumOfVertex() {
return vertexList.size();
}
//返回边
public int getNumOfEdges() {
return numOfEdges;
}
//返回节点 i (下标) 对应的数据
public String getValueByIndex(int i) {
return vertexList.get(i);
}
//返回v1 和 v2 的权值
public int getWeight(int v1, int v2) {
return edges[v1][v2];
}
//显示图对应的矩阵
public void showGraph() {
for (int[] link : edges) {
System.out.println(Arrays.toString(link));
}
}
//返回v1和v2的值
/**
* 插入节点
*
* @param vertex
*/
public void insertVertex(String vertex) {
vertexList.add(vertex);
}
/**
* 添加边
*
* @param v1 点的下标 第几个节点
* @param v2 第二个节点的对应的下标
* @param weight
*/
public void insertEdge(int v1, int v2, int weight) {
edges[v1][v2] = weight;
edges[v2][v1] = weight;
numOfEdges++;
}
}
测试
[0, 1, 1, 0, 0]
[1, 0, 1, 1, 1]
[1, 1, 0, 0, 0]
[0, 1, 0, 0, 0]
[0, 1, 0, 0, 0]