图
1.基本概念介绍:
图:需要表示多对多的关系时,使用图
图中的重要概念:顶点(节点),边,路径,无向图,有向图,带权图(网)
2.图的表示方式:
二维数组(邻接矩阵)
链表(与数组结合)(邻接表)
3.图的创建与深度优先算法分析
图的创建:使用邻接矩阵的方式创建图
深度优先算法:
a.访问初始节点A,并将A节点标记为已访问
b.查找节点A的第一个邻接节点B
c.此时存在两种情况,B存在,继续执行下一步,B不存在,证明A不存在邻接节点,返回第一步重新选择初始节点
d.此时B存在,此时又存在两种情况B没有被访问过,此时将B当成A,递归重复进行上述步骤,寻找节点A的下一个邻接节点,B被访问过,直接需要寻找节点A的下一个邻接节点
4.代码实现
package graph;
import java.util.ArrayList;
import java.util.Arrays;
public class Graph {
private ArrayList<String> vertexList;//节点集合
private int[][] edges;//表示边的邻接矩阵
private int numOfEdges;//表示边的数量
private boolean[] isVistied;//判断是否被访问
public static void main(String[] args) {
String[] strings = {"A","B","C","D","E"};
Graph graph = new Graph(strings.length);
for(int i=0;i<strings.length;i++){
graph.addVertex(strings[i]);
}
graph.addEdge(0,1,1);
graph.addEdge(0,2,1);
graph.addEdge(1,2,1);
graph.addEdge(1,3,1);
graph.addEdge(1,4,1);
graph.showEdges();
graph.dfs();
}
//得到当前节点的第一个邻接节点的下标
public int getFirstNeighbor(int index){
for(int i=0;i<vertexList.size();i++){
if(edges[index][i]>0){
return i;
}
}
return -1;
}
//如果当前节点的邻接节点被访问过,此时需要寻找当前节点的下一个邻接节点
public int getNextNerghbor(int thisIndex,int nextIndex){
for(int j=nextIndex+1;j<vertexList.size();j++){
if(edges[thisIndex][j]>0){
return j;
}
}
return -1;
}
//深度优先算法
public void dfs(boolean[] isVistied,int index){
System.out.println(vertexList.get(index));
isVistied[index] = true;
int w = getFirstNeighbor(index);
while(w!=-1){
if(!isVistied[w]){
dfs(isVistied,w);
}
w = getNextNerghbor(index,w);
}
}
public void dfs(){
for(int i=0;i<vertexList.size();i++){
if(!isVistied[i]){
dfs(isVistied,i);
}
}
}
//构造器
public Graph(int n){
vertexList = new ArrayList<>(n);
edges = new int[n][n];
isVistied = new boolean[n];
numOfEdges = 0;
}
//增加节点
public void addVertex(String vertex){
vertexList.add(vertex);
}
//增加边
public void addEdge(int v1,int v2,int weight){
edges[v1][v2] = weight;
edges[v2][v1] = weight;
numOfEdges ++;
}
//返回节点个数
public int getNumOfVertex(){
return vertexList.size();
}
//返回边的数量
public int getNumOfEdges(){
return numOfEdges;
}
//返回节点i对应的数据
public String getValueByIndex(int i){
return vertexList.get(i);
}
//返回v1,v2的权值
public int getWeight(int v1,int v2){
return edges[v1][v2];
}
//遍历edges
public void showEdges(){
for(int[] edge:edges){
System.out.println(Arrays.toString(edge));
}
}
}
5.图的广度优先算法思路分析
a.访问初始节点A,并将A标记为已访问
b.将节点A放入队列
c.此时判断队列是否为空,不为空继续执行,为空方法结束
d.拿出队列的第一项u
e.查找u的第一个邻接节点w
f.此时分为两种情况,w不存在,回到步骤c,w存在,此时又分为两种情况
g.w存在,也分为两种情况,w被访问,查找u的下一个邻接节点,w未被访问,访问w,并将w记录为被访问状态,将w放入队列,查找u的下一个邻接节点
6.代码实现
//广度有点算法
public void bfs(boolean[] isVistied,int index){
LinkedList<Integer> queue = new LinkedList<>();
int u;//队列中的第一个
int w;//当前节点的第一个邻接节点
System.out.println(vertexList.get(index));
isVistied[index] = true;
queue.addLast(index);
while(!queue.isEmpty()){
u = queue.removeFirst();
w = getFirstNeighbor(u);
while(w != -1){
if(!isVistied[w]){
System.out.println(vertexList.get(w));
isVistied[w] = true;
queue.addLast(w);
}
w = getNextNerghbor(u,w);
}
}
}
public void bfs(){
for(int i=0;i<vertexList.size();i++){
if(!isVistied[i]){
bfs(isVistied,i);
}
}
}