一、應(yīng)用
深度優(yōu)先:是否存在通路,尋找所有解。
廣度優(yōu)先遍歷:尋求最優(yōu)解,尋求最短路徑
1.鄰接矩陣JAVA代碼實(shí)現(xiàn)鄰接矩陣可以使用一個(gè)二維數(shù)組來(lái)表示
public class GraphTest { // 節(jié)點(diǎn) 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 { // 存節(jié)點(diǎn)數(shù)據(jù) private Vertex[] vertices; // 矩陣 private int[][] matrix; // 隊(duì)列,用于BFS private Queuequeue = new LinkedList<>(); // 棧,用于DFS private Stack stack = new Stack<>(); private Map dependencyMap = new HashMap<>(); public Graph(Vertex[] vertices, int[][] matrix) { this.vertices = vertices; this.matrix = matrix; } // 找到未訪問(wèn)過(guò)的鄰接點(diǎn) public List getUnvisitedVertex(int i) { List unvisitedVertices = new ArrayList<>(); for (int j = 0; j < matrix.length; j++) { if (matrix[i][j] > 0 && !vertices[j].isVisited) { unvisitedVertices.add(j); } } return unvisitedVertices; } // 廣度優(yōu)先 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 unvisitedVertices = getUnvisitedVertex(v); unvisitedVertices.forEach(uv -> { queue.offer(uv); dependencyMap.putIfAbsent(uv, v); }); } } } // 深度優(yōu)先 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 unvisitedVertices = getUnvisitedVertex(v); unvisitedVertices.forEach(uv -> stack.push(uv)); } } } // 深度優(yōu)先遞歸實(shí)現(xiàn) public void dfsRecursion(int vertex) { if (!vertices[vertex].isVisited) { vertices[vertex].displayName(); vertices[vertex].isVisited = true; List 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("廣度優(yōu)先搜索:"); graph.bfs(0); graph.clear(); System.out.println("深度優(yōu)先搜索:"); graph.dfs(0); graph.clear(); System.out.println("遞歸深度優(yōu)先搜索:"); graph.dfsRecursion(0); graph.clear(); System.out.println("打印最短路徑:"); graph.printShortestPath(0, 4); } }
打印結(jié)果
廣度優(yōu)先搜索:
name:v0
name:v2
name:v3
name:v1
name:v4
深度優(yōu)先搜索:
name:v0
name:v3
name:v4
name:v2
name:v1
遞歸深度優(yōu)先搜索:
name:v0
name:v2
name:v1
name:v4
name:v3
打印最短路徑:
name:v0
name:v2
name:v3
name:v1
name:v4
v4-->v2-->v0
鄰接表可以使用數(shù)組+鏈表,鏈表+鏈表,哈希表等等數(shù)據(jù)結(jié)構(gòu)來(lái)表示。在java中,map結(jié)構(gòu)非常適合表示鄰接表
public class GraphTest { public static void main(String[] args){ //初始化先建立起各個(gè)節(jié)點(diǎn)信息,以及對(duì)應(yīng)的直接子節(jié)點(diǎn)列表 HashMapmap = 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的最短路徑節(jié)點(diǎn)鏈表 Node target = findTarget("V0","V4",map); //打印出最短路徑的各個(gè)節(jié)點(diǎn)信息 printSearPath(target); } /** * 打印出到達(dá)節(jié)點(diǎn)target所經(jīng)過(guò)的各個(gè)節(jié)點(diǎn)信息 * @param target */ static void printSearPath(Node target) { if (target != null) { System.out.print("找到了目標(biāo)節(jié)點(diǎn):" + target.id + " "); List searchPath = new ArrayList (); 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("步數(shù)最短:"+path); } else { System.out.print("未找到了目標(biāo)節(jié)點(diǎn)"); } } /** * 從指定的開(kāi)始節(jié)點(diǎn) startId ,查詢到目標(biāo)節(jié)點(diǎn)targetId 的最短路徑 * @param startId * @param targetId * @param map * @return */ static Node findTarget(String startId,String targetId,HashMap map) { List hasSearchList = new ArrayList (); LinkedList queue = new LinkedList (); queue.offer(new Node(startId,null)); while(!queue.isEmpty()) { Node node = queue.poll(); if(hasSearchList.contains(node.id)) { //跳過(guò)已經(jīng)搜索過(guò)的,避免重復(fù)或者死循環(huán) continue; } System.out.print("判斷節(jié)點(diǎn):" + node.id +" "); 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; } /** * 節(jié)點(diǎn)對(duì)象 * @author Administrator * */ static class Node{ //節(jié)點(diǎn)唯一id public String id; //該節(jié)點(diǎn)的直接父節(jié)點(diǎn) public Node parent; //該節(jié)點(diǎn)的直接子節(jié)點(diǎn) public List childs = new ArrayList (); public Node(String id,Node parent) { this.id = id; this.parent = parent; } } }
打?。?br>判斷節(jié)點(diǎn):V0
判斷節(jié)點(diǎn):V2
判斷節(jié)點(diǎn):V3
判斷節(jié)點(diǎn):V1
判斷節(jié)點(diǎn):V4
找到了目標(biāo)節(jié)點(diǎn):V4
步數(shù)最短:V0-->V2-->V4
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/75297.html
摘要:圖的定義用圖對(duì)現(xiàn)實(shí)中的系統(tǒng)建模可以用圖對(duì)現(xiàn)實(shí)中的很多系統(tǒng)建模比如對(duì)交通流量建模頂點(diǎn)可以表示街道的十字路口邊可以表示街道加權(quán)的邊可以表示限速或者車道的數(shù)量建模人員可以用這個(gè)系統(tǒng)來(lái)判斷最佳路線及最有可能堵車的街道任何運(yùn)輸系統(tǒng)都可以用圖來(lái)建模比如 圖的定義 用圖對(duì)現(xiàn)實(shí)中的系統(tǒng)建模 可以用圖對(duì)現(xiàn)實(shí)中的很多系統(tǒng)建模. 比如對(duì)交通流量建模, 頂點(diǎn)可以表示街道的十字路口, 邊可以表示街道. 加權(quán)的邊...
摘要:圖的實(shí)現(xiàn)如下采用鄰接表結(jié)構(gòu)實(shí)現(xiàn)。由于本次示例的是無(wú)向圖,因此每個(gè)頂點(diǎn)都互相增加為鄰接點(diǎn)。然而由于本次示例的圖為無(wú)向圖,會(huì)出現(xiàn)重復(fù)遍歷的情況,例如頂點(diǎn)的鄰接點(diǎn)有,的鄰接點(diǎn)有。 圖的定義 圖就是由若干個(gè)頂點(diǎn)和邊連接起來(lái)的一種結(jié)構(gòu)。很多東西都可以用圖來(lái)說(shuō)明,例如人際關(guān)系,或者地圖。 其中圖還分為有向圖和無(wú)向圖。如下就是有向圖 圖的數(shù)據(jù)結(jié)構(gòu) 對(duì)于圖這種關(guān)系,可以通過(guò)兩種方式來(lái)存儲(chǔ)。 領(lǐng)接表 將...
摘要:寫(xiě)在最前本次分享一下通過(guò)廣度優(yōu)先搜索解決八數(shù)碼問(wèn)題并展示其最短路徑的動(dòng)畫(huà)效果。一個(gè)排列中逆序的總數(shù)就稱為這個(gè)排列的逆序數(shù)。如果起始狀態(tài)與結(jié)束狀態(tài)的逆序數(shù)的奇偶性相同,則說(shuō)明狀態(tài)可達(dá),反之亦然。 寫(xiě)在最前 本次分享一下通過(guò)廣度優(yōu)先搜索解決八數(shù)碼問(wèn)題并展示其最短路徑的動(dòng)畫(huà)效果。 歡迎關(guān)注我的博客,不定期更新中—— 效果預(yù)覽 該效果為從[[2, 6, 3],[4, 8, 0],[7, 1, ...
摘要:隊(duì)列和廣度優(yōu)先搜索的一個(gè)常見(jiàn)應(yīng)用是找出從根結(jié)點(diǎn)到目標(biāo)結(jié)點(diǎn)的最短路徑。然后在每一輪中,我們逐個(gè)處理已經(jīng)在隊(duì)列中的結(jié)點(diǎn),并將所有鄰居添加到隊(duì)列中。這就是我們?cè)谥惺褂藐?duì)列的原因。 隊(duì)列和 BFS: 廣度優(yōu)先搜索(BFS)的一個(gè)常見(jiàn)應(yīng)用是找出從根結(jié)點(diǎn)到目標(biāo)結(jié)點(diǎn)的最短路徑。 示例 這里我們提供一個(gè)示例來(lái)說(shuō)明如何使用 BFS 來(lái)找出根結(jié)點(diǎn) A 和目標(biāo)結(jié)點(diǎn) G 之間的最短路徑。 showImg(h...
摘要:散列表上面的地圖向我們展示了如何用廣度優(yōu)先搜索的思想找到北京到廣州的最短路線。在廣度優(yōu)先搜索中,我們需要用到隊(duì)列的這種思想來(lái)實(shí)現(xiàn)查找。建立了下面這個(gè)模型武漢廣州西藏上海上海武漢廣州代碼完整實(shí)現(xiàn),利用遞歸和廣度優(yōu)先搜索的思想實(shí)現(xiàn)。 什么是廣度優(yōu)先搜索? 如果只是是背概念,幼兒園的小朋友都能背下來(lái)念給你聽(tīng)。 假設(shè)看這篇文章的都和我一樣是個(gè)前端工程師,我們要從廣度優(yōu)先搜索(BFS)中學(xué)到什么...
閱讀 2351·2021-11-24 10:27
閱讀 3593·2019-08-30 15:55
閱讀 3355·2019-08-30 15:53
閱讀 2355·2019-08-29 17:27
閱讀 1445·2019-08-26 13:47
閱讀 3558·2019-08-26 10:28
閱讀 927·2019-08-23 15:59
閱讀 2871·2019-08-23 15:19