一、应用
- 深度优先:是否存在通路,寻找所有解。
- 广度优先遍历:寻求最优解,寻求最短路径
1.邻接矩阵JAVA代码实现
邻接矩阵可以使用一个二维数组来表示
public class GraphTest {
// 节点
public static class Vertex {
public String name;
private boolean isVisited;
public Vertex(String name) {
this.name = name;
this.isVisited = false;
}
public void displayName() {
System.out.println("name:" + name);
}
}
// 图
public static class Graph {
// 存节点数据
private Vertex[] vertices;
// 矩阵
private int[][] matrix;
// 队列,用于BFS
private Queue<Integer> queue = new LinkedList<>();
// 栈,用于DFS
private Stack<Integer> stack = new Stack<>();
private Map<Integer, Integer> dependencyMap = new HashMap<>();
public Graph(Vertex[] vertices, int[][] matrix) {
this.vertices = vertices;
this.matrix = matrix;
}
// 找到未访问过的邻接点
public List<Integer> getUnvisitedVertex(int i) {
List<Integer> unvisitedVertices = new ArrayList<>();
for (int j = 0; j < matrix.length; j++) {
if (matrix[i][j] > 0 && !vertices[j].isVisited) {
unvisitedVertices.add(j);
}
}
return unvisitedVertices;
}
// 广度优先
public void bfs(int vertex) {
queue.offer(vertex);
while (!queue.isEmpty()) {
int v = queue.poll();
if (!vertices[v].isVisited) {
vertices[v].displayName();
vertices[v].isVisited = true;
List<Integer> unvisitedVertices = getUnvisitedVertex(v);
unvisitedVertices.forEach(uv -> {
queue.offer(uv);
dependencyMap.putIfAbsent(uv, v);
});
}
}
}
// 深度优先
public void dfs(int vertex) {
stack.push(vertex);
while (!stack.isEmpty()) {
int v = stack.pop();
if (!vertices[v].isVisited) {
vertices[v].displayName();
vertices[v].isVisited = true;
List<Integer> unvisitedVertices = getUnvisitedVertex(v);
unvisitedVertices.forEach(uv -> stack.push(uv));
}
}
}
// 深度优先递归实现
public void dfsRecursion(int vertex) {
if (!vertices[vertex].isVisited) {
vertices[vertex].displayName();
vertices[vertex].isVisited = true;
List<Integer> unvisitedVertices = getUnvisitedVertex(vertex);
unvisitedVertices.forEach(this::dfsRecursion);
}
}
public void printShortestPath(int start, int end) {
bfs(start);
String symbol = "-->";
StringBuilder sb = new StringBuilder();
sb.append(vertices[end].name);
sb.append(symbol);
while (dependencyMap.get(end) != null) {
sb.append(vertices[dependencyMap.get(end)].name);
sb.append(symbol);
end = dependencyMap.get(end);
}
String path = sb.substring(0, sb.lastIndexOf(symbol));
System.out.println(path);
}
public void clear() {
stack.clear();
queue.clear();
dependencyMap.clear();
for (int i = 0; i < vertices.length; i++) {
vertices[i].isVisited = false;
}
}
}
public static void main(String[] args) {
Vertex[] vertices = {
new Vertex("v0"),
new Vertex("v1"),
new Vertex("v2"),
new Vertex("v3"),
new Vertex("v4")
};
int[][] matrix = new int[][]{
{0, 0, 1, 1, 0},
{0, 0, 1, 0, 1},
{1, 1, 0, 0, 1},
{1, 0, 0, 0, 1},
{0, 1, 1, 1, 0}
};
Graph graph = new Graph(vertices, matrix);
System.out.println("广度优先搜索:");
graph.bfs(0);
graph.clear();
System.out.println("深度优先搜索:");
graph.dfs(0);
graph.clear();
System.out.println("递归深度优先搜索:");
graph.dfsRecursion(0);
graph.clear();
System.out.println("打印最短路径:");
graph.printShortestPath(0, 4);
}
}
打印结果
广度优先搜索:
name:v0
name:v2
name:v3
name:v1
name:v4
深度优先搜索:
name:v0
name:v3
name:v4
name:v2
name:v1
递归深度优先搜索:
name:v0
name:v2
name:v1
name:v4
name:v3
打印最短路径:
name:v0
name:v2
name:v3
name:v1
name:v4
v4-->v2-->v0
2.邻接表JAVA代码实现
邻接表可以使用数组+链表,链表+链表,哈希表等等数据结构来表示。在java中,map结构非常适合表示邻接表
public class GraphTest {
public static void main(String[] args){
//初始化先建立起各个节点信息,以及对应的直接子节点列表
HashMap<String,String[]> map = new HashMap<>();
map.put("V0", new String[] {"V2","V3"});
map.put("V1", new String[] {"V2","V4"});
map.put("V2", new String[] {"V0","V1","V4"});
map.put("V3", new String[] {"V0","V4"});
map.put("V4", new String[] {"V1","V2","V3"});
//获取从A到H的最短路径节点链表
Node target = findTarget("V0","V4",map);
//打印出最短路径的各个节点信息
printSearPath(target);
}
/**
* 打印出到达节点target所经过的各个节点信息
* @param target
*/
static void printSearPath(Node target) {
if (target != null) {
System.out.print("找到了目标节点:" + target.id + "\n");
List<Node> searchPath = new ArrayList<Node>();
searchPath.add(target);
Node node = target.parent;
while(node!=null) {
searchPath.add(node);
node = node.parent;
}
String path = "";
for(int i=searchPath.size()-1;i>=0;i--) {
path += searchPath.get(i).id;
if(i!=0) {
path += "-->";
}
}
System.out.print("步数最短:"+path);
} else {
System.out.print("未找到了目标节点");
}
}
/**
* 从指定的开始节点 startId ,查询到目标节点targetId 的最短路径
* @param startId
* @param targetId
* @param map
* @return
*/
static Node findTarget(String startId,String targetId,HashMap<String,String[]> map) {
List<String> hasSearchList = new ArrayList<String>();
LinkedList<Node> queue = new LinkedList<Node>();
queue.offer(new Node(startId,null));
while(!queue.isEmpty()) {
Node node = queue.poll();
if(hasSearchList.contains(node.id)) {
//跳过已经搜索过的,避免重复或者死循环
continue;
}
System.out.print("判断节点:" + node.id +"\n");
if (targetId.equals(node.id)) {
return node;
}
hasSearchList.add(node.id);
if (map.get(node.id) != null && map.get(node.id).length > 0) {
for (String childId : map.get(node.id)) {
queue.offer(new Node(childId,node));
}
}
}
return null;
}
/**
* 节点对象
* @author Administrator
*
*/
static class Node{
//节点唯一id
public String id;
//该节点的直接父节点
public Node parent;
//该节点的直接子节点
public List<Node> childs = new ArrayList<Node>();
public Node(String id,Node parent) {
this.id = id;
this.parent = parent;
}
}
}
打印:
判断节点:V0
判断节点:V2
判断节点:V3
判断节点:V1
判断节点:V4
找到了目标节点:V4
步数最短:V0-->V2-->V4
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。