package Graph;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
public class Graph {
public static void main(String[] args) {
int n = 5;
Graph graph = new Graph(5);
String [] vertex = {"A","B","C","D","E"};//--》[A, B, C, D, E]-->[0,1,2,3,4]
for(String node : vertex){
graph.add(node);
}
//加入边A-B\A-C\B-C\B-D\B-E
graph.addEdges(0,1,1);
graph.addEdges(0,2,1);
graph.addEdges(1,2,1);
graph.addEdges(1,3,1);
graph.addEdges(1,4,1);
//测试邻接矩阵的构建
graph.showGraph();
//测试深度优先遍历
//System.out.println("深度优先遍历:");
//graph.dfs();
//测试广度优先
System.out.println("广度优先遍历:");
graph.bfs();
}
private ArrayList<String> vertexList;//图的结点
private int [][] edges;//图的边,邻接矩阵
private int numOfEdges;//边的数目
private boolean [] isVisited;//记录结点是否被访问过
//构造函数
public Graph(int n){
//传入结点的个数
vertexList = new ArrayList<>(n);
edges = new int[n][n];
isVisited = new boolean[n];
numOfEdges = 0;//边的数目先初始化为0
}
//加入一个
public void add(String vertex){
vertexList.add(vertex);
}
//加入边,构建邻接矩阵
//v1 v2对应结点在数组的下标
public void addEdges(int v1, int v2, int weight){
edges[v1][v2] = weight;
edges[v2][v1] = weight;
numOfEdges += 1;
}
//图中常用的方法
public int getNumOfVertex(){
return vertexList.size();
}
//返回边数
public int getNumOfEdges(){
return numOfEdges;
}
//返回下标对应的结点
public String getValueByIndex(int i){
return vertexList.get(i);
}
//返回边
public int getWeight(int v1, int v2){
return edges[v1][v2];
}
public void showGraph(){
for(int [] link : edges){
System.out.println(Arrays.toString(link));
}
}
//深度优先遍历
//第一步,得到当前结点的第一个邻接节点的下标
public int getFirstNeighbour(int index){
for(int j = 0; j < vertexList.size(); j++){
if(edges[index][j] > 0){
return j;
}
}
return -1;//没有找到
}
//根据前一个邻接节点的下标,获取下一个邻接节点的下标-->获取当前结点的下一个邻接节点的下下个邻接结点
public int getNextNeighbour(int v1, int v2){
for(int j = v2 + 1; j < vertexList.size(); j++){
if(edges[v1][j] > 0){
return j;
}
}
return -1;//没有找到
}
//深度遍历
//i 第一次访问的结点
public void dfs(boolean []isVisited, int i){
//访问改节点
if(i == vertexList.size() - 1){
System.out.print(getValueByIndex(i));
} else {
System.out.print(getValueByIndex(i) + "->");
}
isVisited[i] = true;
int w = getFirstNeighbour(i);
//如果w存在
while (w != -1){
if( !isVisited[w]){
dfs(isVisited,w);
}
//如果w 结点已经被访问过,去查找临街结点的下一个临接结点
w = getNextNeighbour(i,w);
}
}
//对dfs进行重载,因为如果不是连通图,有些结点没被访问
public void dfs(){
//遍历所有的结点
for(int i = 0; i < vertexList.size(); i++){
if(!isVisited[i])
{
dfs(isVisited,i);
}
}
}
//宽度优先遍历
//需要使用一个队列来保存已经访问过的结点的顺序
//以便按这个顺序来访问这些结点的邻接节点
public void bfs(boolean []isVisited, int i){
int u;//队列头的结点的下标
int w;//邻接节点
//队列,记录访问顺序LinkedList模仿队列
LinkedList<Integer> queue = new LinkedList<>();
if(i == vertexList.size() - 1){
System.out.print(getValueByIndex(i));
} else {
System.out.print(getValueByIndex(i) + "->");
}
//标志已被访问
isVisited[i] = true;
//入队
queue.addLast(i);
//访问i 结点的所有邻接节点
while (!queue.isEmpty()){
u = queue.removeFirst();
w = getFirstNeighbour(u);
while (w != -1){
if(!isVisited[w]){
if(w == vertexList.size() - 1){
System.out.print(getValueByIndex(w));
} else{
System.out.print(getValueByIndex(w) + "->");
}
isVisited[w] = true;
//访问该结点并入队
queue.addLast(w);
}
//如果已经访问过,则访问下一邻接节点
w = getNextNeighbour(u,w);
}
}
}
//对广度优先进行重载,以便在遍历非连通图时
public void bfs(){
for(int i = 0; i < vertexList.size(); i++){
if(!isVisited[i]){
bfs(isVisited,i);
}
}
}
}
图的深度优先遍历及广度优先遍历
最新推荐文章于 2023-10-23 22:12:03 发布