本文已参与「新人创作礼」活动,一起开启掘金创作之路。
图的基本介绍和存储形式
图的创建图解和代码实现
我们的顶点使用tring类型,用ArrayList来保存;矩阵我们使用一个二维数组int[][]edges来实现。
代码实现:
package 图;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
public class GraphDemo {
//存储顶点集合(存储A、B、C、D、E)
private ArrayList<String> vertexList;
//存储图对应的邻接矩阵(1表示两点连通,0表示不连通)
private int[][] edges;
//表示边的数目
private int numOfEdges;
//定义个数组boolean[],记录某个节点是否被访问
private boolean[] isVisited;
public static void main(String[] args) {
//测试
int n = 5; //节点的个数
String VertexValue[] = {"A","B","C","D","E"};
GraphDemo g = new GraphDemo(n);
for (String value:
VertexValue) {
g.insert(value);
}
//添加边
//A-B A-C B-C B-D B-E
g.insertEdge(0,1,1); //A-B
g.insertEdge(0,2,1);
g.insertEdge(1,2,1);
g.insertEdge(1,3,1);
g.insertEdge(1,4,1);
//展示图
g.showGraph();
}
//构造器,初始化图的各项数据
public GraphDemo(int n){ //n是顶点的个数
edges = new int[n][n]; //n*n的二维矩阵
vertexList = new ArrayList<>(n); //初始化长度为n
numOfEdges = 0; //边数初始化为0
isVisited = new boolean[5];
}
//图中常用的方法
//1.返回节点的个数
public int getNumOfvertex(){
return vertexList.size();
}
//2.得到边的数目
public int getNumOfEdges(){
return numOfEdges;
}
//3.返回节点i(下标)对应的数据 0->"A" 1->"B" 2->"C"
public String getValueByIndex(int i){
return vertexList.get(i);
}
//4.返回v1、v2的权值
public int getWeight(int v1,int v2){
return edges[v1][v2];
}
//5.显示图对应的矩阵
public void showGraph(){
for (int[] link: edges) {
System.err.println(Arrays.toString(link));
}
}
//插入节点方法
public void insert(String vertex){
vertexList.add(vertex);
}
//添加边的方法
/*
v1表示这一串顶点在邻接矩阵上列的顺序,即第一行第二行第三行...分别对应A、B、C...
v2表示这一串顶点在邻接矩阵上行的顺序,即第一列第二列第三列...分别对应A、B、C...
isChat表示这两个点之间是否有连通(1为连通,0表示不连通)
*/
public void insertEdge(int v1,int v2,int isChat){
edges[v1][v2] = isChat;
edges[v2][v1] = isChat;
numOfEdges++;
}
}
图的深度优先遍历(DFS)
代码实现DFS、BFS:
package 图;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
public class GraphDemo {
//存储顶点集合(存储A、B、C、D、E)
private ArrayList<String> vertexList;
//存储图对应的邻接矩阵(1表示两点连通,0表示不连通)
private int[][] edges;
//表示边的数目
private int numOfEdges;
//定义个数组boolean[],记录某个节点是否被访问
private boolean[] isVisited;
public static void main(String[] args) {
//测试
int n = 5; //节点的个数
String VertexValue[] = {"A","B","C","D","E"};
GraphDemo g = new GraphDemo(n);
for (String value:
VertexValue) {
g.insert(value);
}
//添加边
//A-B A-C B-C B-D B-E
g.insertEdge(0,1,1); //A-B
g.insertEdge(0,2,1);
g.insertEdge(1,2,1);
g.insertEdge(1,3,1);
g.insertEdge(1,4,1);
// g.showGraph();
//测试dfs
// System.out.println("深度遍历");
// g.dfs();
//测试bfs
System.out.println("广度遍历");
g.bfs();
}
//构造器,初始化图的各项数据
public GraphDemo(int n){ //n是顶点的个数
edges = new int[n][n]; //n*n的二维矩阵
vertexList = new ArrayList<>(n); //初始化长度为n
numOfEdges = 0; //边数初始化为0
isVisited = new boolean[5];
}
//深度优先遍历算法:DFS
//得到第一个邻接节点的下标 w
/*
如果存在就返回对应的下标,否则返回-1
*/
public int getFirstNeighbor(int index){
for (int i = 0; i < vertexList.size(); i++) {
if(edges[index][i] > 0) return i;
}
return -1;
}
//根据前一个邻接节点的下标来获取下一个邻接节点
public int getNextNeighbor(int v1,int v2){
for (int i = v2+1; i < vertexList.size(); i++) {
if(edges[v1][i] > 0) return i;
}
return -1;
}
//dfs正经开始
//i一开始就是0
public void dfs(boolean[] isVisited,int i){
//首先我们访问该节点,输出
System.out.print(getValueByIndex(i)+"->");
//将节点设置为已经访问
isVisited[i] = true;
//查找节点i的第一个邻接节点w
int w = getFirstNeighbor(i);
while (w != -1){ //说明有邻接节点
if(!isVisited[w]){
dfs(isVisited,w);
}
//如果w已经被访问过了
w = getNextNeighbor(i,w);
}
}
//对dnf进行一个重载,遍历我们所有的节点,并进行dfs
//作用:遍历所有节点,进行dfs(回溯)
public void dfs(){
for (int i = 0; i < getNumOfvertex(); i++) {
if(!isVisited[i]) {
dfs(isVisited,i);
}
}
}
//对一个节点进行广度优先遍历的方法
private void bfs(boolean[] isVisited,int i){
int u; //表示队列的头结点对应下标
int w; //邻接节点w
//队列,记录节点访问的顺序
LinkedList queue = new LinkedList();
//访问节点,输出节点信息
System.out.print(getValueByIndex(i)+"->");
//标记为已访问
isVisited[i] = true;
//将节点放入队列
queue.addLast(i);
while (!queue.isEmpty()){
//取出队列的头结点下标
u = (Integer)queue.removeFirst();
//得到第一个邻接节点的下标w
w = getFirstNeighbor(u);
while (w != -1){ //找到
//是否访问过?
if(!isVisited[w]){
//为false,说明没被访问过,输出节点信息
System.out.print(getValueByIndex(w)+"->");
//标记被访问
isVisited[w] = true;
//放入队列
queue.addLast(w);
}
//以u为前驱节点,找w后面的下一个节点
w = getNextNeighbor(u,w); //体现出广度优先
}
}
}
//遍历所有节点,都进行广度优先搜索
public void bfs(){
for (int i = 0; i < getNumOfvertex(); i++) {
if(!isVisited[i]){
bfs(isVisited,i);
}
}
}
//图中常用的方法
//1.返回节点的个数
public int getNumOfvertex(){
return vertexList.size();
}
//2.得到边的数目
public int getNumOfEdges(){
return numOfEdges;
}
//3.返回节点i(下标)对应的数据 0->"A" 1->"B" 2->"C"
public String getValueByIndex(int i){
return vertexList.get(i);
}
//4.返回v1、v2的权值
public int getWeight(int v1,int v2){
return edges[v1][v2];
}
//5.显示图对应的矩阵
public void showGraph(){
for (int[] link: edges) {
System.err.println(Arrays.toString(link));
}
}
//插入节点方法
public void insert(String vertex){
vertexList.add(vertex);
}
//添加边的方法
/*
v1表示这一串顶点在邻接矩阵上列的顺序,即第一行第二行第三行...分别对应A、B、C...
v2表示这一串顶点在邻接矩阵上行的顺序,即第一列第二列第三列...分别对应A、B、C...
isChat表示这两个点之间是否有连通(1为连通,0表示不连通)
*/
public void insertEdge(int v1,int v2,int isChat){
edges[v1][v2] = isChat;
edges[v2][v1] = isChat;
numOfEdges++;
}
}