クラスプログラマアルゴリズム(17) - 図一般的に使用されるアルゴリズム:深さ優先(DFS)

免責事項:この記事はブロガーオリジナル記事です、続く BY-SAのCC 4.0を 著作権契約、複製、元のソースのリンクと、この文を添付してください。
このリンク: https://blog.csdn.net/m0_37609579/article/details/100110102

まず、深さ優先探索紹介

図の深さ優先探索(深さ優先探索)、および比較的類似一次ツリートラバーサル。

考えています:すべての頂点を描画された初期状態を仮定するまで、各未訪問の深さ優先探索グラフトラバーサルからその隣人に続く頂点v、頂点への最初のアクセスから始まる、訪問されていません図の頂点vは、すべての通信パスがアクセス可能である必要があります。この方法は、他の頂点へのアクセス権を持っていない場合、頂点は、代替的出発点として、それは、アクセスされるまで、すべての頂点が描画されるまで処理を繰り返す、アクセスされていません。

明らかに、深さ優先探索は、再帰的なプロセスです。

第二に、深さ優先探索のイラスト

1つの無向グラフ深さ優先探索

深さ優先探索を示すために、一例として、「無向グラフ」に続き。

 

深さ優先トラバーサルの上のグラフG1は頂点Aから始まり

 

  1. ステップ1:A.をご覧ください 
  2. ステップ2:C.アクセス(A点に隣接します)最初のステップ訪問した後、次の訪問は、すなわち、「C、D、F」一点に隣接しなければなりません。しかしながら、本明細書の実装では、頂点は「D及びF」の前で順ABCDEFG、Cに格納され、及びC.すること、アクセス 
  3. ステップ3:アクセス(C隣接点)B. 第二段階C訪問した後、次の訪問は、C、即ち、「BとD」を、点に隣接であるべきである(Aがアクセスされた、それが含まれていません)。そして、理由はB Dの前に、最初の訪問のB. 
  4. ステップ4:アクセス(C隣接点)D. アクセスポイントB C Aに隣接したステップ3の後、無未訪問の隣人B;従って、Cは別のDに隣接しているアクセスポイントに戻ります 
  5. ステップ5:F.アクセス(A点に隣接します)「隣接する全ての隣接点が(内側再帰近隣含む)AにBを指すように、」Aは既に訪問されており、アクセスが終了し、アクセスポイントAに戻ったとき、したがって、別のFに隣接しています 
  6. ステップ6:アクセス(F隣接点)G. 
  7. ステップ7:アクセス(当接点G)E.

こうしてアクセスシーケンスである:A - > C - > B - > D - > F. - > G - > E

有向グラフの2深さ優先探索

例として、「有向グラフ」の下に、深さ優先探索を実証します。

深さ優先トラバーサルの上のグラフG2は、頂点Aから始まり

  1. ステップ1:A.をご覧ください 
  2. ステップ2:アクセスB. Aを訪問した後、次にアクセスされるべき側の別の頂点、すなわち、頂点Bです。 
  3. ステップ3:アクセスC. Bを訪問した後、次にアクセスされるべきであり、エッジの別の頂点B、すなわち頂点C、E、F。図は、本明細書で実施、順番に格納された頂点ABCDEFG、第1のアクセスC. 
  4. ステップ4:アクセスE. 次のエッジの頂点Cに、さらにアクセス、すなわち頂点E. 
  5. ステップ5:D.をご覧ください 次に、別の頂点Eは、エッジ、すなわち頂点B、Dをアクセスします 頂点Bにアクセスするため、頂点Dにアクセスされています 
  6. ステップ6:F.をご覧ください それは引き継ぐために戻ってする必要があります「別の頂点Fのアクセスの側面を。」 
  7. ステップ7:アクセスG.

因此访问顺序是:A -> B -> C -> E -> D -> F -> G

三、代码实现

 
  1.  
    private boolean[] isVisited = new boolean[vertextSize];
  2.  
     
  3.  
    /**
  4.  
    * 获取指定顶点的第一个邻接点
  5.  
    *
  6.  
    * @param index
  7.  
    * 指定邻接点
  8.  
    * @return
  9.  
    */
  10.  
    private int getFirstNeighbor(int index) {
  11.  
    for (int i = 0; i < vertexSize; i++) {
  12.  
    if (matrix[index][i] < MAX_WEIGHT && matrix[index][i] > 0) {
  13.  
    return i;
  14.  
    }
  15.  
    }
  16.  
    return -1;
  17.  
    }
  18.  
     
  19.  
    /**
  20.  
    * 获取指定顶点的下一个邻接点
  21.  
    *
  22.  
    * @param v
  23.  
    * 指定的顶点
  24.  
    * @param index
  25.  
    * 从哪个邻接点开始
  26.  
    * @return
  27.  
    */
  28.  
    private int getNextNeighbor(int v, int index) {
  29.  
    for (int i = index+1; i < vertexSize; i++) {
  30.  
    if (matrix[v][i] < MAX_WEIGHT && matrix[v][i] > 0) {
  31.  
    return i;
  32.  
    }
  33.  
    }
  34.  
    return -1;
  35.  
    }
  36.  
     
  37.  
    /**
  38.  
    * 图的深度优先遍历算法
  39.  
    */
  40.  
    private void depthFirstSearch(int i) {
  41.  
    isVisited[i] = true;
  42.  
    int w = getFirstNeighbor(i);
  43.  
    while (w != -1) {
  44.  
    if (!isVisited[w]) {
  45.  
    // 需要遍历该顶点
  46.  
    System.out.println("访问到了:" + w + "顶点");
  47.  
    depthFirstSearch(w); // 进行深度遍历
  48.  
    }
  49.  
    w = getNextNeighbor(i, w); // 第一个相对于w的邻接点
  50.  
    }
  51.  
    }
 
  • 0进去,表示v0
  • 设置v0已访问过,获取v0第一个邻接点w != -1说明有这个邻接点,然后对这个临界点进行判断。
    • 已访问,那就找下一个临界点
    • 未访问,进行访问,然后对该邻接点进行深度优先遍历

四、总结

  • 遍历规则:不断的沿着顶点的深度方向遍历。顶点的深度方向是指它的邻接点方向。
  • 它从图中某个顶点v出发,访问此顶点,然后从顶点的未被访问的邻接点出发深度优先遍历图,直至图中所有和v有路径相通的顶点都被访问到。
  • 简单说,就是顶点将第一个邻接点当作左孩子,其它邻接点都当做右孩子。最后排成一棵树。
  • 深度优先遍历是指先遍历到最深层次然后再探索邻接点,接着又遍历最深层次。二叉树的先序遍历就是一种深度优先遍历。

我的微信公众号:架构真经(id:gentoo666),分享Java干货,高并发编程,热门技术教程,微服务及分布式技术,架构设计,区块链技术,人工智能,大数据,Java面试题,以及前沿热门资讯等。每日更新哦!

参考资料:

  1. https://blog.csdn.net/Strive_Y/article/details/81810012
  2. https://www.jianshu.com/p/23b55db1adc0

おすすめ

転載: www.cnblogs.com/anymk/p/11521521.html