数据结构与算法练习---图的创建与遍历(深度优先/广度优先)
程序员文章站
2022-05-20 19:06:09
...
package graph;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
/**
* 创建图
*/
public class Graph {
private ArrayList<String> vertexList; //储存顶点元素的集合
private int[][] edges; //储存边使用的二维数组
private int edgeNum; //保存边的数量
private boolean[] isVisit;
public static void main(String[] args) {
String[] vertexs = {"A", "B", "C", "D", "E"};
String[] vertexs1 = {"1", "2", "3", "4", "5", "6", "7", "8"};
Graph graph = new Graph(5);
Graph graph1 = new Graph(8);
//设置顶点
for (int i = 0; i < vertexs.length; i++) {
graph.addVertex(vertexs[i]);
}
for (int i = 0; i < vertexs1.length; i++) {
graph1.addVertex(vertexs1[i]);
}
//设置边
graph.addEdeg(0, 1, 1);//A->B
graph.addEdeg(0, 2, 1);//A->C
graph.addEdeg(2, 1, 1);//C->B
graph.addEdeg(1, 3, 1);//B->D
graph.addEdeg(1, 4, 1);//B->E/
// 设置边
graph1.addEdeg(0, 1, 1);
graph1.addEdeg(0, 2, 1);
graph1.addEdeg(1, 3, 1);
graph1.addEdeg(1, 4, 1);
graph1.addEdeg(3, 7, 1);
graph1.addEdeg(4, 7, 1);//B->E
graph1.addEdeg(2, 5, 1);//B->E
graph1.addEdeg(2, 6, 1);
graph1.addEdeg(5, 6, 1);
//展示
graph.show();
//深度优先遍历
System.out.println("深度优先!");
graph.deepFirstSearch();
//重置标记数组
graph.resetVisit();
System.out.println();
//广度优先遍历
System.out.println("广度优先!");
graph.breadFirstSearch();
System.out.println("--------------------------------split---------------------------------------");
//展示
graph1.show();
//深度优先遍历
System.out.println("深度优先!");
graph1.deepFirstSearch();
//重置标记数组
graph1.resetVisit();
System.out.println();
//广度优先遍历
System.out.println("广度优先!");
graph1.breadFirstSearch();
}
//构造器
public Graph(int n){
//初始化各个成员变量
vertexList = new ArrayList<>(n);
edges = new int[n][n];
edgeNum = 0;
isVisit = new boolean[n];
}
//根据传入的当前元素的坐标找到其第一个邻接元素 如果有则返回该元素的下标,如果没有则返回-1
public int getFirstNeighbor(int index){
for(int i = 0; i < vertexList.size(); i++){
int temp = edges[index][i];
if(temp > 0){
return i;
}
}
return -1;
}
//根据前一个邻接结点的索引找到下一个邻接结点的索引
public int getNextNeighbor(int v1, int v2){
for (int i = 1 + v2; i < vertexList.size(); i++) {
if(edges[v1][i] > 0){
return i;
}
}
return -1;
}
/**
* 提供空参的重载方法
* 在该方法中提供各个结点的索引回溯遍历
*/
public void breadFirstSearch(){
for (int i = 0; i < vertexList.size(); i++) {
if(!isVisit[i]){
breadFirstSearch(isVisit , i);
}
}
}
/**
根据广度优先算法遍历图
* 找到初始结点的邻接结点。并将其保存于队列中,从队列中按顺序取出数据,并重复上述步骤完成图的遍历
*/
public void breadFirstSearch(boolean[] isVisit, int i){
//输出当前结点,并将其状态改为以访问
System.out.print(vertexList.get(i) + "=>");
isVisit[i] = true;
//声明队列 linkedList也是队列实现类的一种
LinkedList<Integer> queue = new LinkedList<>();
//将当前元素的索引加入队列中
queue.addLast(i);
//只要队列不为空就继续该循环
//两个循环为本方法的核心代码 使用两层while循环和一个队列产生了一种类似于递归的效果,可以一层一层向下深入
while (!queue.isEmpty()){
//取出当前元素的下标
Integer u = queue.removeFirst();
//找出与其相连的下一个元素
int w = getFirstNeighbor(u);
//下一个元素不为空则继续该循环
while (w != -1){
//若该元素违背访问 则输出该元素 并将其置为以访问状态 并将当前元素加入链表中
if(!isVisit[w]){
System.out.print(vertexList.get(w) + "=>");
isVisit[w] = true;
queue.addLast(w);
}
//若该元素已经被访问过则继续找出与当前相连通的其他元素
w = getNextNeighbor(u, w);
}
}
}
/**
* 根据深度优先算法遍历图
* 从一条可行的通路直到最后一个满足要求的结点
* @param isVisit
* @param i
*/
public void deepFirstSearch(boolean[] isVisit , int i){
//输出当前结点
System.out.print(vertexList.get(i) + "-->");
//将当前结点置为以访问
isVisit[i] = true;
//循环递归访问其他结点
int w = getFirstNeighbor(i);
//只要当前元素还有邻接元素就继续循环
while (w != -1){
//只要邻接元素未被访问过就递归调用该方法
if(!isVisit[w]){
deepFirstSearch(isVisit , w);
}
//若当前邻接元素已被访问过,则查找他的下一个邻接元素只要不为空则继续循环
w = getNextNeighbor(i , w);
}
}
/**
* 提供空参的重载方法
* 在该方法中提供各个结点的索引回溯遍历
*/
public void deepFirstSearch(){
for (int i = 0; i < vertexList.size(); i++) {
if(!isVisit[i]){
deepFirstSearch(isVisit , i);
}
}
}
//添加顶点
public void addVertex(String vertex){
vertexList.add(vertex);
}
//添加边和权值
public void addEdeg(int v1 , int v2, int weight){
//创建的图为无向图 故 A->B <=> B->A
edges[v1][v2] = weight;
edges[v2][v1] = weight;
edgeNum++;
}
//返回图的顶点个数
public int getVertexNum(){
return vertexList.size();
}
//返回图边的个数
public int getEdgeNum(){
return edgeNum;
}
//返回顶点下标对应的顶点元素
public String getVertexByIndex(int index){
return vertexList.get(index);
}
//返回v1,v2处对应的权值
public int getWeight(int v1, int v2){
return edges[v1][v2];
}
//显示邻接矩阵
public void show(){
for (int[] edge : edges) {
System.out.println(Arrays.toString(edge));
}
}
//重置标记数组
public void resetVisit(){
for (int i = 0; i < isVisit.length; i++) {
isVisit[i] = false;
}
}
}
下一篇: 397. 整数替换
推荐阅读
-
PHP实现二叉树的深度优先与广度优先遍历方法
-
Python数据结构与算法之图的广度优先与深度优先搜索算法示例
-
数据结构与算法-----BFS与DFS(广度优先搜索与深度优先搜索)
-
数据结构与算法_深度优先搜索(DFS)与广度优先搜索(BFS)详解
-
Java数据结构与算法:图、图的概念、深度优先搜索DFS、广度优先搜索BFS、思路分析、代码实现
-
【数据结构】图的遍历——深度优先搜索DFS、广度优先搜索BFS
-
Java数据结构与算法——深度优先搜索与广度优先搜索
-
数据结构与算法——广度和深度优先搜索
-
数据结构与算法————图的遍历DFS深度优先搜索和BFS广度优先搜索
-
java数据结构与算法之二叉树深度优先和广度优先遍历