1.定义
- 顶点 : 如上图中每个元素都是一个顶点 如 A B C D E F
- 边 : 顶点到顶点直接建立的连接关系叫做边 如 AB AD AC等等
- 度 : 每个顶点有多少条边就是该顶点的度 如A的度为3 C的度为3 B的度为2等等
2.图的分类
- 生活社交网其实就是一个图结构
- 比如微信 QQ 微博 等等
- 像微信/QQ中的每个用户就是顶点 而用户之间添加好友后 这个添加关系就是边 用户添加的好友个数就是度
- 有向图和无向图
- 在微博中的图和微信 qq有些区别 比如用户A关注B 但是B可以不关注A 这样我们用图表示可以在上面基础上添加一个箭头指向 A关注B 可以A指向B 但是B不指向A C 和 F就是相互关注 这样的图叫做有向图 同理没有指向关系的叫做无向图
- 带权图
- 如下每条边都偶一个权重 可以看做是好友亲密度
3.图的存储
3.1邻接矩形存储
- : 底层依赖一个二维数组
- 无向图 : 如果2个顶点之间有边 就标记为 1
- 有向图 : A顶点指向B顶点 B没有指向A顶点 则 (A,B)为1 (B,A)为0
- 带权无向图存储权重
- 无向存储 : (x,y) x为横 y为纵
- (1,1) (1,4) (4,1)等 没有边 所以为0
- (1,2) (2,1) (2,3)等 有边 所以为 1
- 有向存储 : 指向谁 谁那存储为1
- (1,2) 1指向2 所以为1
- (2,1) 2没有指向1 所以为0 等等
- 带权无向 存储的是权重
- (1,3) 权重为3
- (2,3)权重为2 等等
- 该方法
- 优点是直观 简单
- 缺点是浪费空间 我们可以发现其无向图是对称的 也就是说 只需要一半就可以完成需求 相当于浪费了一半空间
3.2 邻接链表存储
- 有点类似于一个散列表 其每个顶点对应一条链表
- 有向图 链表存储与该顶点相连指向的顶点
- 无向图 链表存储的是与该顶点相连的顶点
- 带权图 在链表每个节点里在添加一个元素存储器权值
- 优点 : 节省空间存储
- 缺点 : 查询效率低
4.图的应用
- 构建一个无向图
package com.example.ioimage;
import java.util.LinkedList;
/**
* 无向图
*/
public class GraphSeaerh {
//顶点个数
private int poings;
//邻接表可以看做是一个散列表 头部存储的是各个顶点 链表其他节点存储与该顶点相连的其他顶点
private LinkedList<Integer> linkedList[];
public GraphSeaerh(int poings) {
this.poings = poings;
linkedList = new LinkedList[this.poings];
//初始化每个槽位的链表
for (int i = 0; i < this.poings; i++) {
linkedList[i] = new LinkedList<>();//令数组每个槽位都是一个链表
}
}
/**
* 向数组中添加顶点(边)
* @param i 新添加的顶点
* @param j 和新顶点有关系的顶点
*/
public void addEdge(int i,int j){
//无向图中 新添加一个顶点后 是相互指向 一条边存储两回
//注意 : 无向图中顶点值 对应数组下标
linkedList[i].add(j);
linkedList[j].add(i);
}
}
4.1广度优先搜索 BFS
- 是一种地毯式层层推进搜索策略 即先查找离起始顶点最近的 然后查找次近的 依次向外搜索 一般使用队列结构进行辅助查询
- 步骤
- 把源顶点放到队列里
- 从来队列里弹出第一个顶点 并检查其是否为目标 如果找到目标 就返回结果 否则把它没有检查过的直接子顶点添加到队列里
- 当队列为空时 代表整张图都检查过了 存在则返回 不存在就返回null
- 重复第二步进行查询
- 代码实现
/**
* 广度搜索
*
* @param source 源顶点
* @param target 目标顶点
*/
public void bfs(int source, int target) {
if (source == target) {
return;
}
//定义一个boolean数组 记录顶点是否被访问过
boolean[] booleans = new boolean[this.poings];
booleans[source] = true;
//定义一个队列
Queue<Integer> queue = new LinkedList<>();
queue.add(source);//把源顶点加入队列
//定义一个数组 记录源顶点和目标顶点之间的线路
int[] prev = new int[this.poings];
for (int i = 0; i < prev.length; i++) {
prev[i] = -1;
}
while (!queue.isEmpty()) {//当队列非空时
Integer poll = queue.poll();//取出队列元素 该元素被移除队列
//从邻接表里取出和顶点相连的顶点元素
for (int i = 0; i < linkedList[poll].size(); i++) {
//取出和顶点poll相连的顶点p_connection
Integer p_connection = linkedList[poll].get(i);
//判断该顶点是否被访问过 true表示被访问过
//如果没访问过 则取出与该顶点相连接的顶点
if (!booleans[p_connection]) {
//记录p_connection之前的顶点为poll
prev[p_connection] = poll;
//判断与顶点poll相连的p_connection是否是目标顶点
if (p_connection == target) {
//打印访问线路
print(prev, source, target);
return;
}
//标记p_connection已经被访问过
booleans[p_connection] = true;
queue.add(p_connection);
}
}
}
}
public void print(int[] prev, int source, int target) {
if (prev[target] != -1 && source != target) {
print(prev, source, prev[target]);
}
System.out.print(target + " --> ");
}
- 测试
public static void main(String[] args) {
GraphSeaerh graphSeaerh = new GraphSeaerh(8);
graphSeaerh.addEdge(0,1);
graphSeaerh.addEdge(0,3);
graphSeaerh.addEdge(1,2);
graphSeaerh.addEdge(1,4);
graphSeaerh.addEdge(3,4);
graphSeaerh.addEdge(2,5);
graphSeaerh.addEdge(4,5);
graphSeaerh.addEdge(4,6);
graphSeaerh.addEdge(5,7);
graphSeaerh.addEdge(6,7);
graphSeaerh.bfs(0,7);
}
4.2 深度优先搜索 DFS
-
“走迷宫” 假设你站在迷宫的某个岔路口,然后想找到出口。你随意选择一个岔路口来走,走着走着发现走不通的时候,你就回退到上一个岔路口,重新选择一条路继续走,直到最终找到出口
-
从某个顶点到另外一个顶点 如下图 从s到t 使用深度递归算法 实线表示遍历 虚线表示回退 最终找到路径 (可以发现其并不是最近的路线)
- 代码实现
/**
* 深度搜索
* @param source
* @param target
*/
public void dfs(int source, int target) {
if (source == target){
return;
}
//定义一个boolean数组 记录顶点是否被访问过
boolean[] booleans = new boolean[this.poings];
booleans[source] = true;
//定义一个数组 记录源顶点和目标顶点之间的线路
int[] prev = new int[this.poings];
for (int i = 0; i < prev.length; i++) {
prev[i] = -1;
}
resourceDFS(source,target,booleans,prev);
print(prev,source,target);
}
//递归查询顶点p到目标顶点间的线路图
public void resourceDFS(int source, int target, boolean[] booleans, int[] prev) {
if (found){
return;
}
booleans[source] = true;//标记当前顶点已经被访问过了
if (source == target) {
//如果当前顶点和目标顶点相同 则代表已经查找到了 把全局变量修改为true
this.found = true;
return;
}
//遍历当前顶点相连的所有顶点
for (int i = 0; i < linkedList[source].size(); i++) {
//获取与顶点p相连的顶点
Integer p_connection = linkedList[source].get(i);
//判断该顶点是否被访问过 true表示被访问过
//如果没访问过 则取出与该顶点相连接的顶点
if (!booleans[p_connection]) {
prev[p_connection] = source;
resourceDFS(p_connection,target,booleans,prev);
}
}
}
-
测试
-
public static void main(String[] args) { GraphSeaerh graphSeaerh = new GraphSeaerh(8); graphSeaerh.addEdge(0,1); graphSeaerh.addEdge(0,3); graphSeaerh.addEdge(1,2); graphSeaerh.addEdge(1,4); graphSeaerh.addEdge(3,4); graphSeaerh.addEdge(2,5); graphSeaerh.addEdge(4,5); graphSeaerh.addEdge(4,6); graphSeaerh.addEdge(5,7); graphSeaerh.addEdge(6,7); graphSeaerh.bfs(0,4); System.out.println(); graphSeaerh.dfs(0,4); }
5.完整代码
package com.example.ioimage;
import java.util.LinkedList;
import java.util.Queue;
/**
* 无向图
*/
public class GraphSeaerh {
public static void main(String[] args) {
GraphSeaerh graphSeaerh = new GraphSeaerh(8);
graphSeaerh.addEdge(0,1);
graphSeaerh.addEdge(0,3);
graphSeaerh.addEdge(1,2);
graphSeaerh.addEdge(1,4);
graphSeaerh.addEdge(3,4);
graphSeaerh.addEdge(2,5);
graphSeaerh.addEdge(4,5);
graphSeaerh.addEdge(4,6);
graphSeaerh.addEdge(5,7);
graphSeaerh.addEdge(6,7);
graphSeaerh.bfs(0,4);
System.out.println();
graphSeaerh.dfs(0,4);
}
//顶点个数
private int poings;
//邻接表可以看做是一个散列表 头部存储的是各个顶点 链表其他节点存储与该顶点相连的其他顶点
private LinkedList<Integer> linkedList[];
public GraphSeaerh(int poings) {
this.poings = poings;
linkedList = new LinkedList[this.poings];
//初始化每个槽位的链表
for (int i = 0; i < this.poings; i++) {
linkedList[i] = new LinkedList<>();//令数组每个槽位都是一个链表
}
}
/**
* 向数组中添加顶点(边)
*
* @param i 新添加的顶点
* @param j 和新顶点有关系的顶点
*/
public void addEdge(int i, int j) {
//无向图中 新添加一个顶点后 是相互指向 一条边存储两回
//注意 : 无向图中顶点值 对应数组下标
linkedList[i].add(j);
linkedList[j].add(i);
}
/**
* 广度搜索
*
* @param source 源顶点
* @param target 目标顶点
*/
public void bfs(int source, int target) {
if (source == target) {
return;
}
//定义一个boolean数组 记录顶点是否被访问过
boolean[] booleans = new boolean[this.poings];
booleans[source] = true;
//定义一个队列
Queue<Integer> queue = new LinkedList<>();
queue.add(source);//把源顶点加入队列
//定义一个数组 记录源顶点和目标顶点之间的线路
int[] prev = new int[this.poings];
for (int i = 0; i < prev.length; i++) {
prev[i] = -1;
}
while (!queue.isEmpty()) {//当队列非空时
Integer poll = queue.poll();//取出队列元素 该元素被移除队列
//从邻接表里取出和顶点相连的顶点元素
for (int i = 0; i < linkedList[poll].size(); i++) {
//取出和顶点poll相连的顶点p_connection
Integer p_connection = linkedList[poll].get(i);
//判断该顶点是否被访问过 true表示被访问过
//如果没访问过 则取出与该顶点相连接的顶点
if (!booleans[p_connection]) {
//记录p_connection之前的顶点为poll
prev[p_connection] = poll;
//判断与顶点poll相连的p_connection是否是目标顶点
if (p_connection == target) {
//打印访问线路
print(prev, source, target);
return;
}
//标记p_connection已经被访问过
booleans[p_connection] = true;
queue.add(p_connection);
}
}
}
}
private boolean found = false;//记录是否查找到目标顶点
/**
* 深度搜索
* @param source
* @param target
*/
public void dfs(int source, int target) {
if (source == target){
return;
}
//定义一个boolean数组 记录顶点是否被访问过
boolean[] booleans = new boolean[this.poings];
booleans[source] = true;
//定义一个数组 记录源顶点和目标顶点之间的线路
int[] prev = new int[this.poings];
for (int i = 0; i < prev.length; i++) {
prev[i] = -1;
}
resourceDFS(source,target,booleans,prev);
print(prev,source,target);
}
//递归查询顶点p到目标顶点间的线路图
public void resourceDFS(int source, int target, boolean[] booleans, int[] prev) {
if (found){
return;
}
booleans[source] = true;//标记当前顶点已经被访问过了
if (source == target) {
//如果当前顶点和目标顶点相同 则代表已经查找到了 把全局变量修改为true
this.found = true;
return;
}
//遍历当前顶点相连的所有顶点
for (int i = 0; i < linkedList[source].size(); i++) {
//获取与顶点p相连的顶点
Integer p_connection = linkedList[source].get(i);
//判断该顶点是否被访问过 true表示被访问过
//如果没访问过 则取出与该顶点相连接的顶点
if (!booleans[p_connection]) {
prev[p_connection] = source;
resourceDFS(p_connection,target,booleans,prev);
}
}
}
public void print(int[] prev, int source, int target) {
if (prev[target] != -1 && source != target) {
print(prev, source, prev[target]);
}
System.out.print(target + " --> ");
}
}
1.定义
- 顶点 : 如上图中每个元素都是一个顶点 如 A B C D E F
- 边 : 顶点到顶点直接建立的连接关系叫做边 如 AB AD AC等等
- 度 : 每个顶点有多少条边就是该顶点的度 如A的度为3 C的度为3 B的度为2等等
2.图的分类
- 生活社交网其实就是一个图结构
- 比如微信 QQ 微博 等等
- 像微信/QQ中的每个用户就是顶点 而用户之间添加好友后 这个添加关系就是边 用户添加的好友个数就是度
- 有向图和无向图
- 在微博中的图和微信 qq有些区别 比如用户A关注B 但是B可以不关注A 这样我们用图表示可以在上面基础上添加一个箭头指向 A关注B 可以A指向B 但是B不指向A C 和 F就是相互关注 这样的图叫做有向图 同理没有指向关系的叫做无向图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w8U0Mq5F-1606460388384)(图.assets/image-20201126140258847.png)]
- 带权图
- 如下每条边都偶一个权重 可以看做是好友亲密度
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RY84D1lw-1606460388387)(图.assets/image-20201126140609743.png)]
3.图的存储
3.1邻接矩形存储
- : 底层依赖一个二维数组
- 无向图 : 如果2个顶点之间有边 就标记为 1
- 有向图 : A顶点指向B顶点 B没有指向A顶点 则 (A,B)为1 (B,A)为0
- 带权无向图存储权重
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xKjldldf-1606460388389)(图.assets/image-20201126154651791.png)]
- 无向存储 : (x,y) x为横 y为纵
- (1,1) (1,4) (4,1)等 没有边 所以为0
- (1,2) (2,1) (2,3)等 有边 所以为 1
- 有向存储 : 指向谁 谁那存储为1
- (1,2) 1指向2 所以为1
- (2,1) 2没有指向1 所以为0 等等
- 带权无向 存储的是权重
- (1,3) 权重为3
- (2,3)权重为2 等等
- 该方法
- 优点是直观 简单
- 缺点是浪费空间 我们可以发现其无向图是对称的 也就是说 只需要一半就可以完成需求 相当于浪费了一半空间
3.2 邻接链表存储
- 有点类似于一个散列表 其每个顶点对应一条链表
- 有向图 链表存储与该顶点相连指向的顶点
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rBiX1yXS-1606460388392)(图.assets/image-20201126173916238.png)]
- 无向图 链表存储的是与该顶点相连的顶点
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A8BKCGZr-1606460388392)(图.assets/image-20201126173035121.png)]
- 带权图 在链表每个节点里在添加一个元素存储器权值
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OmeTiIrk-1606460388393)(图.assets/image-20201126174432450.png)]
- 优点 : 节省空间存储
- 缺点 : 查询效率低
4.图的应用
- 构建一个无向图
package com.example.ioimage;
import java.util.LinkedList;
/**
* 无向图
*/
public class GraphSeaerh {
//顶点个数
private int poings;
//邻接表可以看做是一个散列表 头部存储的是各个顶点 链表其他节点存储与该顶点相连的其他顶点
private LinkedList<Integer> linkedList[];
public GraphSeaerh(int poings) {
this.poings = poings;
linkedList = new LinkedList[this.poings];
//初始化每个槽位的链表
for (int i = 0; i < this.poings; i++) {
linkedList[i] = new LinkedList<>();//令数组每个槽位都是一个链表
}
}
/**
* 向数组中添加顶点(边)
* @param i 新添加的顶点
* @param j 和新顶点有关系的顶点
*/
public void addEdge(int i,int j){
//无向图中 新添加一个顶点后 是相互指向 一条边存储两回
//注意 : 无向图中顶点值 对应数组下标
linkedList[i].add(j);
linkedList[j].add(i);
}
}
4.1广度优先搜索 BFS
- 是一种地毯式层层推进搜索策略 即先查找离起始顶点最近的 然后查找次近的 依次向外搜索 一般使用队列结构进行辅助查询
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QvumeB3n-1606460388395)(图.assets/image-20201127094346888.png)]
- 步骤
- 把源顶点放到队列里
- 从来队列里弹出第一个顶点 并检查其是否为目标 如果找到目标 就返回结果 否则把它没有检查过的直接子顶点添加到队列里
- 当队列为空时 代表整张图都检查过了 存在则返回 不存在就返回null
- 重复第二步进行查询
- 代码实现
/**
* 广度搜索
*
* @param source 源顶点
* @param target 目标顶点
*/
public void bfs(int source, int target) {
if (source == target) {
return;
}
//定义一个boolean数组 记录顶点是否被访问过
boolean[] booleans = new boolean[this.poings];
booleans[source] = true;
//定义一个队列
Queue<Integer> queue = new LinkedList<>();
queue.add(source);//把源顶点加入队列
//定义一个数组 记录源顶点和目标顶点之间的线路
int[] prev = new int[this.poings];
for (int i = 0; i < prev.length; i++) {
prev[i] = -1;
}
while (!queue.isEmpty()) {//当队列非空时
Integer poll = queue.poll();//取出队列元素 该元素被移除队列
//从邻接表里取出和顶点相连的顶点元素
for (int i = 0; i < linkedList[poll].size(); i++) {
//取出和顶点poll相连的顶点p_connection
Integer p_connection = linkedList[poll].get(i);
//判断该顶点是否被访问过 true表示被访问过
//如果没访问过 则取出与该顶点相连接的顶点
if (!booleans[p_connection]) {
//记录p_connection之前的顶点为poll
prev[p_connection] = poll;
//判断与顶点poll相连的p_connection是否是目标顶点
if (p_connection == target) {
//打印访问线路
print(prev, source, target);
return;
}
//标记p_connection已经被访问过
booleans[p_connection] = true;
queue.add(p_connection);
}
}
}
}
public void print(int[] prev, int source, int target) {
if (prev[target] != -1 && source != target) {
print(prev, source, prev[target]);
}
System.out.print(target + " --> ");
}
- 测试
public static void main(String[] args) {
GraphSeaerh graphSeaerh = new GraphSeaerh(8);
graphSeaerh.addEdge(0,1);
graphSeaerh.addEdge(0,3);
graphSeaerh.addEdge(1,2);
graphSeaerh.addEdge(1,4);
graphSeaerh.addEdge(3,4);
graphSeaerh.addEdge(2,5);
graphSeaerh.addEdge(4,5);
graphSeaerh.addEdge(4,6);
graphSeaerh.addEdge(5,7);
graphSeaerh.addEdge(6,7);
graphSeaerh.bfs(0,7);
}
4.2 深度优先搜索 DFS
-
“走迷宫” 假设你站在迷宫的某个岔路口,然后想找到出口。你随意选择一个岔路口来走,走着走着发现走不通的时候,你就回退到上一个岔路口,重新选择一条路继续走,直到最终找到出口
-
从某个顶点到另外一个顶点 如下图 从s到t 使用深度递归算法 实线表示遍历 虚线表示回退 最终找到路径 (可以发现其并不是最近的路线)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aewlLI9m-1606460388396)(图.assets/image-20201127141053992.png)]
- 代码实现
/**
* 深度搜索
* @param source
* @param target
*/
public void dfs(int source, int target) {
if (source == target){
return;
}
//定义一个boolean数组 记录顶点是否被访问过
boolean[] booleans = new boolean[this.poings];
booleans[source] = true;
//定义一个数组 记录源顶点和目标顶点之间的线路
int[] prev = new int[this.poings];
for (int i = 0; i < prev.length; i++) {
prev[i] = -1;
}
resourceDFS(source,target,booleans,prev);
print(prev,source,target);
}
//递归查询顶点p到目标顶点间的线路图
public void resourceDFS(int source, int target, boolean[] booleans, int[] prev) {
if (found){
return;
}
booleans[source] = true;//标记当前顶点已经被访问过了
if (source == target) {
//如果当前顶点和目标顶点相同 则代表已经查找到了 把全局变量修改为true
this.found = true;
return;
}
//遍历当前顶点相连的所有顶点
for (int i = 0; i < linkedList[source].size(); i++) {
//获取与顶点p相连的顶点
Integer p_connection = linkedList[source].get(i);
//判断该顶点是否被访问过 true表示被访问过
//如果没访问过 则取出与该顶点相连接的顶点
if (!booleans[p_connection]) {
prev[p_connection] = source;
resourceDFS(p_connection,target,booleans,prev);
}
}
}
-
测试
-
public static void main(String[] args) { GraphSeaerh graphSeaerh = new GraphSeaerh(8); graphSeaerh.addEdge(0,1); graphSeaerh.addEdge(0,3); graphSeaerh.addEdge(1,2); graphSeaerh.addEdge(1,4); graphSeaerh.addEdge(3,4); graphSeaerh.addEdge(2,5); graphSeaerh.addEdge(4,5); graphSeaerh.addEdge(4,6); graphSeaerh.addEdge(5,7); graphSeaerh.addEdge(6,7); graphSeaerh.bfs(0,4); System.out.println(); graphSeaerh.dfs(0,4); }
5.完整代码
package com.example.ioimage;
import java.util.LinkedList;
import java.util.Queue;
/**
* 无向图
*/
public class GraphSeaerh {
public static void main(String[] args) {
GraphSeaerh graphSeaerh = new GraphSeaerh(8);
graphSeaerh.addEdge(0,1);
graphSeaerh.addEdge(0,3);
graphSeaerh.addEdge(1,2);
graphSeaerh.addEdge(1,4);
graphSeaerh.addEdge(3,4);
graphSeaerh.addEdge(2,5);
graphSeaerh.addEdge(4,5);
graphSeaerh.addEdge(4,6);
graphSeaerh.addEdge(5,7);
graphSeaerh.addEdge(6,7);
graphSeaerh.bfs(0,4);
System.out.println();
graphSeaerh.dfs(0,4);
}
//顶点个数
private int poings;
//邻接表可以看做是一个散列表 头部存储的是各个顶点 链表其他节点存储与该顶点相连的其他顶点
private LinkedList<Integer> linkedList[];
public GraphSeaerh(int poings) {
this.poings = poings;
linkedList = new LinkedList[this.poings];
//初始化每个槽位的链表
for (int i = 0; i < this.poings; i++) {
linkedList[i] = new LinkedList<>();//令数组每个槽位都是一个链表
}
}
/**
* 向数组中添加顶点(边)
*
* @param i 新添加的顶点
* @param j 和新顶点有关系的顶点
*/
public void addEdge(int i, int j) {
//无向图中 新添加一个顶点后 是相互指向 一条边存储两回
//注意 : 无向图中顶点值 对应数组下标
linkedList[i].add(j);
linkedList[j].add(i);
}
/**
* 广度搜索
*
* @param source 源顶点
* @param target 目标顶点
*/
public void bfs(int source, int target) {
if (source == target) {
return;
}
//定义一个boolean数组 记录顶点是否被访问过
boolean[] booleans = new boolean[this.poings];
booleans[source] = true;
//定义一个队列
Queue<Integer> queue = new LinkedList<>();
queue.add(source);//把源顶点加入队列
//定义一个数组 记录源顶点和目标顶点之间的线路
int[] prev = new int[this.poings];
for (int i = 0; i < prev.length; i++) {
prev[i] = -1;
}
while (!queue.isEmpty()) {//当队列非空时
Integer poll = queue.poll();//取出队列元素 该元素被移除队列
//从邻接表里取出和顶点相连的顶点元素
for (int i = 0; i < linkedList[poll].size(); i++) {
//取出和顶点poll相连的顶点p_connection
Integer p_connection = linkedList[poll].get(i);
//判断该顶点是否被访问过 true表示被访问过
//如果没访问过 则取出与该顶点相连接的顶点
if (!booleans[p_connection]) {
//记录p_connection之前的顶点为poll
prev[p_connection] = poll;
//判断与顶点poll相连的p_connection是否是目标顶点
if (p_connection == target) {
//打印访问线路
print(prev, source, target);
return;
}
//标记p_connection已经被访问过
booleans[p_connection] = true;
queue.add(p_connection);
}
}
}
}
private boolean found = false;//记录是否查找到目标顶点
/**
* 深度搜索
* @param source
* @param target
*/
public void dfs(int source, int target) {
if (source == target){
return;
}
//定义一个boolean数组 记录顶点是否被访问过
boolean[] booleans = new boolean[this.poings];
booleans[source] = true;
//定义一个数组 记录源顶点和目标顶点之间的线路
int[] prev = new int[this.poings];
for (int i = 0; i < prev.length; i++) {
prev[i] = -1;
}
resourceDFS(source,target,booleans,prev);
print(prev,source,target);
}
//递归查询顶点p到目标顶点间的线路图
public void resourceDFS(int source, int target, boolean[] booleans, int[] prev) {
if (found){
return;
}
booleans[source] = true;//标记当前顶点已经被访问过了
if (source == target) {
//如果当前顶点和目标顶点相同 则代表已经查找到了 把全局变量修改为true
this.found = true;
return;
}
//遍历当前顶点相连的所有顶点
for (int i = 0; i < linkedList[source].size(); i++) {
//获取与顶点p相连的顶点
Integer p_connection = linkedList[source].get(i);
//判断该顶点是否被访问过 true表示被访问过
//如果没访问过 则取出与该顶点相连接的顶点
if (!booleans[p_connection]) {
prev[p_connection] = source;
resourceDFS(p_connection,target,booleans,prev);
}
}
}
public void print(int[] prev, int source, int target) {
if (prev[target] != -1 && source != target) {
print(prev, source, prev[target]);
}
System.out.print(target + " --> ");
}
}