一、基础知识:
(1)基本概念:
(2)图的表示方式:
邻接矩阵:
邻接表:
二、代码实现:
包含图的简单实现,深度优先遍历、广度优先遍历。
深度优先遍历:
广度优先遍历:
代码汇总:
package graph;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
/**
* 图的简单实现
*/
public class GraphDemo {
private ArrayList<String> vertexList; // 存储顶点集合
private int[][] edges; // 定义邻接矩阵
private int numOfEdges; //表示 图中 边的数目
private boolean[] isVisited; // 表示是 该 节点 否被访问
public GraphDemo(int n) {
//初始化 邻接矩阵 和 存储顶点集合
vertexList = new ArrayList<String>(n);
edges = new int[n][n];
numOfEdges = 0;
isVisited = new boolean[n];
}
public static void main(String[] args) {
int n = 8;
// String vertex[] = {"A", "B", "C", "D", "E"};
String vertex[] = {"1", "2", "3", "4", "5", "6", "7", "8"};
GraphDemo graph = new GraphDemo(n);
//首先添加顶点:
for (String ver : vertex){
graph.insertVertex(ver);
}
//添加边:
// 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.insertEdge(0, 1, 1);
graph.insertEdge(0, 2, 1);
graph.insertEdge(1, 3, 1);
graph.insertEdge(1, 4, 1);
graph.insertEdge(3, 7, 1);
graph.insertEdge(4, 7, 1);
graph.insertEdge(2, 5, 1);
graph.insertEdge(2, 6, 1);
graph.insertEdge(5, 6, 1);
graph.showGraph();
System.out.println("深度优先遍历:");
graph.depthFirstSearch();
System.out.println();
System.out.println("广度优先遍历:");
graph.breadthFirstSearch();
}
//得到第一个邻接节点的下标(存在就返回对应的下标,否则返回-1)
/**
* index 从 0 开始
* @param index
* @return 找到就返回对应的下标,否则就返回 -1
*/
public int getFirstNeighbor(int index){
for (int i = 0; i < vertexList.size(); i++){
if ( edges[index][i] > 0){
return i;
}
}
return -1;
}
//根据前一个邻接节点 的 下标 来获取下一个邻接节点的下标:(需要知道前一个邻接节点的 下标(v1,v2))
public int getNextNeighbor(int v1, int v2){
for (int j = v2 + 1; j < vertexList.size(); j++){
if (edges[v1][j] > 0){
return j;
}
}
return -1;
}
//******************************************************
//深度优先遍历:
private void depthFirstSearch(boolean[] isVisited, int i){
// 首先访问到该节点时,输出:
System.out.print(getValueOfVertex(i) + "->");
//将此节点设置为已经访问:
isVisited[i] = true;
//查找节点 i 的第一个邻接节点
int firstNeighbor = getFirstNeighbor(i);
while ( firstNeighbor != -1){ //查找,(进入到while循环说明有)
if (!isVisited[firstNeighbor]){ //判断是否被访问过
//如果没有被访问过,就进行遍历
depthFirstSearch(isVisited,firstNeighbor); //存在且 未被访问 则进行 遍历
}
//如果已经被访问过:需要找下一个节点
firstNeighbor = getNextNeighbor(i, firstNeighbor);
}
}
//对depthFirstSearch进行重载,遍历所有的节点:
public void depthFirstSearch(){
isVisited = new boolean[vertexList.size()];
// for (int i = 0 ; i < getNumOfVertex(); i++){
// if (!isVisited[i]){ // 若没有 被访问 ,则进行 遍历
// depthFirstSearch(isVisited,i);
// }
// }
depthFirstSearch(isVisited,0);
}
//********************************************************
//广度优先遍历:
private void breadthFirstSearch(boolean[] isVisited, int i){
int u; //队列头节点对应的下标
int w; // 邻接节点w
//创建一个队列记录节点的访问顺序
LinkedList<Object> queue = new LinkedList<>();
System.out.print(getValueOfVertex(i) + "->");
isVisited[i] = true;
queue.addLast(i);
while (! queue.isEmpty()){
u = (Integer) queue.removeFirst();
w = getFirstNeighbor(u);
while (w != -1){
if (!isVisited[w]){
System.out.print(getValueOfVertex(w) + "->");
isVisited[w] = true;
queue.addLast(w);
}
w = getNextNeighbor(u,w);
}
}
}
public void breadthFirstSearch(){
isVisited = new boolean[vertexList.size()];
breadthFirstSearch(isVisited,0);
}
//***************************************************
//返回结点的个数:
public int getNumOfVertex(){
return vertexList.size();
}
//显示 图 对应的 矩阵: 就是遍历 邻接矩阵
public void showGraph(){
for (int[] edge:edges){
System.out.println(Arrays.toString(edge));
}
}
//得到边的数目:
public int getNumOfEdges(){
return numOfEdges;
}
//返回结点 i (下标)对应的数据(即 节点的信息)
public String getValueOfVertex(int i){
return vertexList.get(i);
}
//返回 两顶点间 对应的权值: 两顶点间的权值在 邻接矩阵中 得到
public int getWeight(int v1, int v2){
return edges[v1][v2];
}
//插入结点:
public void insertVertex(String vertex){
vertexList.add(vertex);
}
//添加边:即 顶点 与 顶点 之间的关系(是否能够直接连通)
/**
* 指定 两个顶点的下标 v1 , v2 ,再指定 权值 weight (为 1 表示 能直连,0表示不能直连)
* @param v1
* @param v2
* @param weight
*/
public void insertEdge(int v1, int v2, int weight){
edges[v1][v2] = weight;
edges[v2][v1] = weight;
numOfEdges++; //表示 边数 增加了 一条
}
}