日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Carson带你学数据结构:手把手带你了解 ”图“ 所有知识!(含DFS、BFS)

發布時間:2024/3/13 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Carson带你学数据结构:手把手带你了解 ”图“ 所有知识!(含DFS、BFS) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

本文主要講解 數據結構中的圖 結構,包括 深度優先搜索(DFS)、廣度優先搜索(BFS)、最小生成樹算法等,希望你們會喜歡。


目錄


1. 簡介

  • 數據結構的中屬于 圓形結構 的邏輯結構
  • 具體介紹如下


2. 基礎概念

  • 在圖的數據結構中,有許多基礎概念,如 邊類型、圖頂點 & 邊間的關系等等
  • 具體請看下圖


3. 類型

圖的類型分為很多種,具體如下:

3.1 有向圖 & 無向圖

3.2 連通圖

  • 定義
    圖中任意頂點都是連通的圖

  • 具體相關概念
    對于有向圖 & 無向圖,連通圖的的具體概念又不同,具體如下

對于無向圖:

對于有向圖:

3.3 其余類型圖


4. 存儲結構

圖的存儲結構共有5種,具體請看下圖


5. 圖的遍歷

數據結構:圖文詳解二叉樹(遍歷、類型、操作)

5.1 定義

從圖中某1頂點出發,遍歷圖中其余所有頂點 & 使每1個頂點僅被訪問1次

5.2 遍歷方式

深度優先遍歷(DFS)、廣度優先遍歷(BFS)

5.3 具體介紹

5.3.1 深度優先遍歷( DFS )
  • 簡介

  • 算法示意圖

  • 具體實現:遞歸 & 非遞歸

此處圖的存儲結構 = 鄰接矩陣

import java.util.Stack;public class MyGraph {/*** 準備工作1:設置變量*/private int vexnum; // 存放圖中頂點數量private char[] vertices; // 存放結點數據private int [][] arcs; // 存放圖的所有邊private boolean[] visited;// 記錄節點是否已被遍歷/*** 準備工作2:初始化圖的頂點數量、數據 & 邊*/public MyGraph(int n){vexnum = n;vertices = new char[n];visited = new boolean[n];arcs = new int[n][n];}/*** 圖的深度優先遍歷算法實現:遞歸* 類似 前序遍歷*/public void DFSTraverse(){// 1. 初始化所有頂點的訪問標記// 即,都是未訪問狀態for (int i = 0; i < vexnum; i++) {visited[i] = false;}// 2. 深度優先遍歷頂點(從未被訪問的頂點開始)for(int i=0;i < vexnum;i++){if(visited[i]==false){// 若是連通圖,只會執行一次traverse(i); // ->>看關注1}}}/*** 關注1:鄰接矩陣的深度優先搜索遞歸算法* 即,從第i個頂點開始深度優先遍歷*/private void traverse(int i){// 1. 標記第i個頂點已遍歷visited[i] = true;// 2. (輸出)訪問當前遍歷的頂點visit(i);// 3. 遍歷鄰接矩陣中第i個頂點的所有鄰接頂點for(int j=0;j<vexnum;j++){// a. 若當前頂點的鄰接頂點存在 & 未被訪問,則遞歸 深度優先搜索 算法if(arcs[i][j]==1 && visited[j]==false){// b. 將當前頂點的鄰接頂點作為當前頂點,遞歸 深度優先搜索 算法traverse(j);}}}/*** 輔助算法1:訪問頂點值*/public void visit(int i){System.out.print(vertices[i] + " ");}/*** 圖的深度優先遍歷算法實現:非遞歸* 原理:采用 棧實現*/public void DFSTraverse2(){// 1. 初始化頂點訪問標記// 全部標記為:未訪問for (int i = 0; i < vexnum; i++) {visited[i] = false;}// 2. 創建棧Stack<Integer> s = new Stack<Integer>();for(int i=0 ; i<vexnum; i++){// 3. 若該頂點未被訪問if(!visited[i]){// 4. 入棧該頂點s.add(i);do{// 出棧int curr = s.pop();// 如果該節點還沒有被遍歷,則遍歷該節點并將子節點入棧if(visited[curr]==false){// 遍歷并打印visit(curr);visited[curr] = true;// 沒遍歷的子節點入棧for(int j=vexnum-1; j>=0 ; j-- ){if(arcs[curr][j]==1 && visited[j]==false){s.add(j);}}}}while(!s.isEmpty());}}}/*** 測試(遞歸 & 非遞歸)*/public static void main(String[] args) {// 1. 初始化圖的結構(頂點數量 = 9)MyGraph g = new MyGraph(9);// 2. 設置頂點數據char[] vertices = {'A','B','C','D','E','F','G','H','I'};g.setVertices(vertices);// 3. 設置邊g.addEdge(0, 1);g.addEdge(0, 5);g.addEdge(1, 0);g.addEdge(1, 2);g.addEdge(1, 6);g.addEdge(1, 8);g.addEdge(2, 1);g.addEdge(2, 3);g.addEdge(2, 8);g.addEdge(3, 2);g.addEdge(3, 4);g.addEdge(3, 6);g.addEdge(3, 7);g.addEdge(3, 8);g.addEdge(4, 3);g.addEdge(4, 5);g.addEdge(4, 7);g.addEdge(5, 0);g.addEdge(5, 4);g.addEdge(5, 6);g.addEdge(6, 1);g.addEdge(6, 3);g.addEdge(6, 5);g.addEdge(6, 7);g.addEdge(7, 3);g.addEdge(7, 4);g.addEdge(7, 6);g.addEdge(8, 1);g.addEdge(8, 2);g.addEdge(8, 3);// 4. 執行 圖的深度優先遍歷:(遞歸 & 非遞歸)System.out.println("深度優先遍歷(遞歸)");g.DFSTraverse();System.out.println("深度優先遍歷(非遞歸)");g.DFSTraverse2();}/*** 輔助算法1:添加邊(無向圖)*/public void addEdge(int i, int j) {// 邊的頭尾不能為同一節點if (i == j) return;// 將鄰接矩陣的第i行第j列的元素值置為1;arcs[i][j] = 1;// 將鄰接矩陣的第j行第i列的元素值置為1;arcs[j][i] = 1;// 設置為1代表2頂點之間存在 邊 (設置相等原因 = 鄰接矩陣 是對稱的)}/*** 輔助算法2:設置頂點數據*/public void setVertices(char[] vertices) {this.vertices = vertices;} }
  • 測試結果
深度優先遍歷(遞歸) A B C D E F G H I 深度優先遍歷(非遞歸) A B C D E F G H I
  • 特別注意
    對于圖的存儲結構 = 鄰接表實現,只需要將 存儲邊 的2維數組 改成鏈表即可。

  • 圖的存儲結構 = 鄰接矩陣 / 鄰接表 的性能對比

5.3.2 廣度優先遍歷(BFS)
  • 簡介

  • 算法示意圖

  • 具體流程

注:G 比 I 先訪問的原因 = 用數組存儲頂點時,G的下標 比 I的下標小(按ABCDEFGHI順序存儲)

  • 具體實現

非遞歸:采用隊列

import java.util.LinkedList; import java.util.Queue; import java.util.Stack;public class MyGraph {/*** 準備工作1:設置變量*/private int vexnum; // 存放圖中頂點數量private char[] vertices; // 存放結點數據private int [][] arcs; // 存放圖的所有邊private boolean[] visited;// 記錄節點是否已被遍歷/*** 準備工作2:初始化圖的頂點數量、數據 & 邊*/public MyGraph(int n){vexnum = n;vertices = new char[n];visited = new boolean[n];arcs = new int[n][n];}/*** 廣度優先搜索 算法實現* 原理:非遞歸(采用隊列)*/public void BFS(){// 1. 初始化所有頂點的訪問標記// 即,設置為未訪問狀態for (int i = 0; i < vexnum; i++) {visited[i] = false;}// 2. 創建隊列Queue<Integer> q=new LinkedList<Integer>();// 3. 對所有頂點做遍歷循環(從第1個頂點開始)// 若遍歷完畢,則結束整個層序遍歷for(int i=0;i < vexnum;i++){// 4. 若當前頂點未被訪問,就進行處理// 若當前頂點已被訪問,則回到3進行判斷if( visited[i]==false ) {// 5. (輸出)訪問當前頂點visit(i);// 6. 標記當前頂點已被訪問visited[i] = true;// 7. 入隊當前頂點q.add(i);// 8.判斷當前隊列是否為空// 若為空則跳出循環,回到3進行判斷while(!q.isEmpty()) {// 9. 出隊隊首元素 & 將出隊的元素 賦值為 當前頂點i = q.poll();// 10. 遍歷當前頂點的所有鄰接點// 若遍歷完畢,則回到8判斷for(int j=0; j< vexnum ; j++){// 11. 若當前頂點的鄰接頂點存在 & 未被訪問,則執行處理// 否則回到10判斷if(arcs[i][j]==1 && visited[j]==false){// 12. (輸出)訪問當前頂點的鄰接頂點visit(j);// 13. 標記當前頂點的鄰接頂點已被訪問visited[j] = true;// 14. 入隊當前頂點的鄰接頂點q.add(j);}}}}}}/*** 輔助算法1:訪問該頂點*/public void visit(int i){System.out.print(vertices[i] + " ");}/** * 測試算法*/public static void main(String[] args) {// 1. 初始化圖的結構(頂點數量 = 9MyGraph g = new MyGraph(9);// 2. 設置頂點數據char[] vertices = {'A','B','C','D','E','F','G','H','I'};g.setVertices(vertices);// 3. 設置邊g.addEdge(0, 1);g.addEdge(0, 5);g.addEdge(1, 0);g.addEdge(1, 2);g.addEdge(1, 6);g.addEdge(1, 8);g.addEdge(2, 1);g.addEdge(2, 3);g.addEdge(2, 8);g.addEdge(3, 2);g.addEdge(3, 4);g.addEdge(3, 6);g.addEdge(3, 7);g.addEdge(3, 8);g.addEdge(4, 3);g.addEdge(4, 5);g.addEdge(4, 7);g.addEdge(5, 0);g.addEdge(5, 4);g.addEdge(5, 6);g.addEdge(6, 1);g.addEdge(6, 3);g.addEdge(6, 5);g.addEdge(6, 7);g.addEdge(7, 3);g.addEdge(7, 4);g.addEdge(7, 6);g.addEdge(8, 1);g.addEdge(8, 2);g.addEdge(8, 3);// 4. 執行 圖的廣度優先遍歷(非遞歸)System.out.print("廣度優先遍歷(非遞歸):");g.BFS();}/*** 輔助算法1:添加邊(無向圖)*/public void addEdge(int i, int j) {// 邊的頭尾不能為同一節點if (i == j) return;// 將鄰接矩陣的第i行第j列的元素值置為1;arcs[i][j] = 1;// 將鄰接矩陣的第j行第i列的元素值置為1;arcs[j][i] = 1;// 設置為1代表2頂點之間存在 邊 (設置相等原因 = 鄰接矩陣 是對稱的)}/*** 輔助算法2:設置頂點數據*/public void setVertices(char[] vertices) {this.vertices = vertices;}}
  • 執行結果
廣度優先遍歷(非遞歸):A B F C G I E D H

5.4 遍歷方式對比


6. 最小生成樹

本節主要講解 圖中的 最小生成樹

6.1 定義

構造 連通網圖 的最小成本生成樹

  • 網圖:帶有權值的圖
  • 最小成本:用(n-1)條邊將 含n個頂點的連通圖 連接起來 & 使得權值和最小
  • 6.2 尋找最小生成樹的算法

    • 主要包括:(Prim)普利姆算法 & (Kruskal)克魯斯卡爾算法
    • 具體介紹如下

    6.2.1 (Prim)普利姆算法

    • 算法概述

    • 算法原理流程示意圖

    • 舉例說明

    6.2.2(Kruskal)克魯斯卡爾算法

    • 算法概述

    6.3 算法對比


    7. 最短路徑

    7.1 定義

    • 對于非網圖(無權值),最短路徑 = 兩頂點間經過的邊數最少的路徑
    • 對于網圖(有權值):最短路徑 = 兩頂點間經過的邊上權值和最少的路徑

    第1個頂點 = 源點、第2個頂點 = 終點

    7.2 需解決的問題

    從源點 -> 其余各頂點的最短路徑

    7.3 尋找最短路徑 算法

    • 主要包括:迪杰斯特拉算法(Dijkstra)、弗洛伊德算法(Floyd)

    • 具體介紹如下


    8. 總結

    • 本文主要講解了數據結構中的圖
    • 下面我將繼續對 數據結構,有興趣可以繼續關注Carson_Ho的安卓開發筆記

    幫頂 / 評論點贊!因為你的鼓勵是我寫作的最大動力!

    總結

    以上是生活随笔為你收集整理的Carson带你学数据结构:手把手带你了解 ”图“ 所有知识!(含DFS、BFS)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。