数据结构与算法(Java)之图
Posted 达少Rising
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构与算法(Java)之图相关的知识,希望对你有一定的参考价值。
深度优先与广度优先
package com.weeks.graph;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
/**
* @author 达少
* @version 1.0
*
* 无向图
*
*/
public class Graph {
private ArrayList<String> vertexList;//用于存储图的顶点
private int[][] edges;//用处存储顶点与顶点的联系(边)
private int edgesNumber;//记录边的数量
private boolean[] isVisited;//记录对应的顶点有没有被访问过
public static void main(String[] args) {
//创建图对象
Graph graph = new Graph(5);
//插入顶点
graph.insertVertex("A");
graph.insertVertex("B");
graph.insertVertex("C");
graph.insertVertex("D");
graph.insertVertex("E");
//插入边A-B,A-C,B-C,B-E,B-D
graph.inertEdge(0, 1, 1);
graph.inertEdge(0, 2, 1);
graph.inertEdge(1, 2, 1);
graph.inertEdge(1, 3, 1);
graph.inertEdge(1, 4, 1);
//显示图
graph.showGraph();
//测试深度优先遍历
// graph.dfs();
//测试广度优先遍历
graph.bfs();
}
/**
* 初始化图
* @param n 表示改图有多少个顶点
*
*/
public Graph(int n){
this.vertexList = new ArrayList<String>(n);
this.edges = new int[n][n];
this.edgesNumber = 0;//初始化为零
this.isVisited = new boolean[n];//大小就是顶点的数量
}
//插入顶点
public void insertVertex(String vertex){
vertexList.add(vertex);
}
//插入边
/**
*
* @param v1 表示边连接的一端的顶点的下标
* @param v2 表示边连接的另一端的顶点的下标
* @param weight 表示这条边的权值,我们定义的无向图,两个顶点之间有直接关联的权值为1,否则为0
*/
public void inertEdge(int v1, int v2, int weight){
edges[v1][v2] = 1;
edges[v2][v1] = 1;
edgesNumber++;//边的个数加1
}
//获取图顶点的个数
public int getVertexNumber(){
return vertexList.size();
}
//获取边的个数
public int getEdgesNumber(){
return edgesNumber;
}
//显示图,就是遍历二维数组
public void showGraph(){
for (int[] line : edges){
System.out.println(Arrays.toString(line));
}
}
//获取对应的顶点值
public String getValueByIndex(int index){
if(index < vertexList.size()){
return vertexList.get(index);
}
return null;
}
//获取一个顶点的第一个邻接顶点
public int getFirstNeighbor(int index){
//遍历二维数组edges的第index行(index代表第几个顶点)
for (int i = 0; i < vertexList.size(); i++) {
//当edges[index][i]不为0则说明index顶点与i顶点连接的
if(edges[index][i] > 0){//说明找到了,放回顶点下标
return i;
}
}
//找不到就返回-1
return -1;
}
//获取一个顶点的第一个邻接顶点的下一个临界点
/**
*
* @param v1 当前顶点
* @param v2 当前顶点的第一个邻接顶点
* @return 如果存在v1的第一个邻接点的下一个结点
*/
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;
}
//深度优先遍历图
private void dfs(boolean[] isVisited, int index){
//首先访问当前顶点
System.out.print(getValueByIndex(index) + "->");
//将当前顶点设置为已被访问过
isVisited[index] = true;
//当前顶点的第一个邻接顶点
int w = getFirstNeighbor(index);
while(w != -1){//说明存在下一个邻接点
//如果w没有被访问过,就继续递归
if(!isVisited[w]){
dfs(isVisited, w);
}
//如果被访问过,则需要找到当前顶点的下一个顶点
w = getNextNeighbor(index, w);
}
}
//上面的dfs的逻辑只是完成了对一个顶点的操作,接下来就是循环遍历顶点列表
//对每个顶点进行同样的操作
public void dfs(){
for(int i = 0; i < getVertexNumber(); i++){
if(!isVisited[i]) {
dfs(this.isVisited, i);
}
}
}
//广度优先遍历
private void bfs(boolean[] isVisited, int index){
//队列,记录访问顶点的顺序
LinkedList queue = new LinkedList();
//记录当前队列的头部元素对应的顶点下标
int u;
//记录当前顶点的第一个邻接点的下标
int w;
//访问当前顶点
System.out.print(getValueByIndex(index) + "=>");
//将当前顶点设置为以访问
isVisited[index] = true;
//将当前点加入访问列表中
queue.addLast(index);
//当队列不为空,取出队列中的顶点
while(!queue.isEmpty()){
//取出头节点的下标
u = (Integer) queue.removeFirst();
//得到第一个邻接点的下标
w = getFirstNeighbor(u);
if(w != -1){//证明找到邻接点
//判断是否被访问过
if(!isVisited[w]){//没有被访问
//那么就访问w这个顶点
System.out.print(getValueByIndex(w) + "=>");
//并将w顶点设置为被访问
isVisited[w] = true;
//并将w顶点加入访问列表中
queue.addLast(w);
}
//如果被访问过那么将继续查找u顶点的下一个邻接顶点
w = getNextNeighbor(u, w);//体现了广度优先
}
}
}
//上面的bfs的逻辑只是完成了对一个顶点的操作,接下来就是循环遍历顶点列表
//对每个顶点进行同样的操作
public void bfs(){
for(int i = 0; i < getVertexNumber(); i++){
if(!isVisited[i]){
bfs(this.isVisited, i);
}
}
}
}
以上是关于数据结构与算法(Java)之图的主要内容,如果未能解决你的问题,请参考以下文章