Java 由淺入深帶你掌握圖的遍歷
1.圖的遍歷
從圖中某一頂點出發(fā)訪問圖中其余頂點,且每個頂點僅被訪問一次
圖的遍歷有兩種深度優(yōu)先遍歷DFS、廣度優(yōu)先遍歷BFS
2.深度優(yōu)先遍歷
深度優(yōu)先遍歷以深度為優(yōu)先進行遍歷,簡單來說就是每次走到底。類似于二叉樹的前序遍歷
思路:
1.以某一個頂點為起點進行深度優(yōu)先遍歷,并標(biāo)記該頂點已訪問
2.以該頂點為起點選取任意一條路徑一直遍歷到底,并標(biāo)記訪問過的頂點
3.第2步遍歷到底后回退到上一個頂點,重復(fù)第2步
4.遍歷所有頂點結(jié)束
根據(jù)遍歷思路可知,這是一個遞歸的過程,其實DFS與回溯基本相同。
遍歷:
以此圖為例進行深度優(yōu)先遍歷
static void dfs(int[][] graph,int idx,boolean[]visit) { int len = graph.length; //訪問過 if(visit[idx]) return; //訪問該頂點 System.out.println("V"+idx); //標(biāo)志頂點 visit[idx] = true; for(int i = 1;i < len;i++) { //訪問該頂點相連的所有邊 if(graph[idx][i] == 1) { //遞歸進行dfs遍歷 dfs(graph, i, visit); } } }
遍歷結(jié)果:
V1
V2
V3
V4
V5
V6
V7
V8
V9
創(chuàng)建圖的代碼:
public static void main(String[] args) { Scanner scanner = new Scanner(System.in); //頂點數(shù) 以1開始 int n = scanner.nextInt(); int[][] graph = new int[n+1][n+1]; //邊數(shù) int m = scanner.nextInt(); for(int i = 1;i <= m;i++) { int v1 = scanner.nextInt(); int v2 = scanner.nextInt(); graph[v1][v2] = 1; graph[v2][v1] = 1; } //標(biāo)記數(shù)組 false表示未訪問過 boolean[] visit = new boolean[n+1]; dfs(graph, 1, visit); }
3.利用DFS判斷有向圖是否存在環(huán)
思路:遍歷某一個頂點時,如果除了上一個頂點之外,還存在其他相連頂點被訪問過,則必然存在環(huán)
//默認(rèn)無環(huán) static boolean flag = false; public static void main(String[] args) { Scanner scanner = new Scanner(System.in); //頂點數(shù) 以1開始 int n = scanner.nextInt(); int[][] graph = new int[n+1][n+1]; //邊數(shù) int m = scanner.nextInt(); for(int i = 1;i <= m;i++) { int v1 = scanner.nextInt(); int v2 = scanner.nextInt(); graph[v1][v2] = 1; } //標(biāo)記數(shù)組 true為訪問過 boolean[] visit = new boolean[n+1]; dfs(graph, 1, visit,1); if(flag) System.out.println("有環(huán)"); } static void dfs(int[][] graph,int idx,boolean[]visit,int parent) { int len = graph.length; System.out.println("V"+idx); //標(biāo)記頂點 visit[idx] = true; for(int i = 1;i < len;i++) { //訪問該頂點相連的所有邊 if(graph[idx][i] == 1) { if( !visit[i] ) { dfs(graph, i, visit,idx); } else if(idx != i) { flag = true; } } } }
注意:是有向圖判斷是否存在環(huán),無向圖判斷是否存在環(huán)無意義,因為任意兩個存在路徑的頂點都可以是環(huán)
4.廣度優(yōu)先遍歷
廣度優(yōu)先遍歷是以廣度(寬度)為優(yōu)先進行遍歷。類似于二叉樹的層序遍歷
思路:
1.以某一個頂點為起點進行廣度優(yōu)先遍歷,并標(biāo)記該頂點已訪問
2.訪問所有與該頂點相連且未被訪問過的頂點,并標(biāo)記訪問過的頂點
3.以第2步訪問所得頂點為起點重復(fù)1、2步驟
4.遍歷所有頂點結(jié)束
通過隊列來輔助遍歷,隊列出隊順序即是廣度優(yōu)先遍歷結(jié)果
遍歷
以此圖為例,采用鄰接矩陣的方式創(chuàng)建圖,進行BFS遍歷
static void bfs(int[][] graph) { int len = graph.length; //標(biāo)記數(shù)組 false表示未訪問過 boolean[] visit = new boolean[len]; //輔助隊列 Queue<Integer> queue = new LinkedList<>(); queue.offer(1); visit[1] = true; while(!queue.isEmpty()) { int num = queue.poll(); System.out.println("V"+num); //遍歷該頂點所有相連頂點 for(int i = 1;i < len;i++) { //相連并且沒有被訪問過 if(graph[num][i] == 1 && !visit[i]) { queue.offer(i); visit[i] = true; } } } }
遍歷結(jié)果:
V1
V2
V6
V3
V7
V9
V5
V4
V8
創(chuàng)建圖的代碼
public static void main(String[] args) { Scanner scanner = new Scanner(System.in); //頂點數(shù) 以1開始 int n = scanner.nextInt(); int[][] graph = new int[n+1][n+1]; //邊數(shù) int m = scanner.nextInt(); for(int i = 1;i <= m;i++) { int v1 = scanner.nextInt(); int v2 = scanner.nextInt(); graph[v1][v2] = 1; graph[v2][v1] = 1; } bfs(graph); }
到此這篇關(guān)于Java 由淺入深帶你掌握圖的遍歷的文章就介紹到這了,更多相關(guān)Java 圖的遍歷內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringSecurity自動登錄流程與實現(xiàn)詳解
這篇文章主要介紹了SpringSecurity自動登錄流程與實現(xiàn)詳解,所謂的自動登錄是在訪問鏈接時瀏覽器自動攜帶上了Cookie中的Token交給后端校驗,如果刪掉了Cookie或者過期了同樣是需要再次驗證的,需要的朋友可以參考下2024-01-01JavaWeb?Servlet技術(shù)及其應(yīng)用實踐
這篇文章主要介紹了JavaWeb?Servlet技術(shù),Servlet指在服務(wù)器端執(zhí)行的一段Java代碼,可以接收用戶的請求和返回給用戶響應(yīng)結(jié)果,感興趣想要詳細了解可以參考下文2023-05-05java實時監(jiān)控文件行尾內(nèi)容的實現(xiàn)
這篇文章主要介紹了java實時監(jiān)控文件行尾內(nèi)容的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-02-02Spring Data Jpa 自動生成表結(jié)構(gòu)的方法示例
這篇文章主要介紹了Spring Data Jpa 自動生成表結(jié)構(gòu)的方法示例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04MyBatis-plus報錯Property ‘sqlSessionFactory‘ or 
這篇文章主要給大家介紹了MyBatis-plus 報錯 Property ‘sqlSessionFactory‘ or ‘sqlSessionTemplate‘ are required的兩種解決方法,如果遇到相同問題的朋友可以參考借鑒一下2023-12-12