目次
1.深さ優先探索(DFS)
1.理解する
1.1二分木のプレオーダートラバーサルを確認します
深さ優先走査は、二分木での事前順序走査のようなものです。1つの極が最後に挿入され、前に移動してから前のノードに戻って、別の分岐があるかどうかを確認することが不可能であることがわかります。ある場合は、1つの極が最後に挿入されます。ない場合は、最後のノードに戻り、左右のノードがトラバースされるまで繰り返します。
のは、見てみましょうの先行順走査バイナリツリーを最初:
前順走査手順を
①:ルートノードAから始めて、左サブツリー、左サブツリー、左サブツリーを無意識に歩きます... Gに到達するまで、彼には左子ノードがありません。つまり、左サブツリーがありません。この図のバイナリツリーが比較的簡単で、かつので、右の子の木は、Gが行くする権利サブツリーを持っていない、それはに戻ります前のノードのD G ;
②:Dの左のサブツリーはすでに歩いているので、Dの右のサブツリーに移動します。
③:Dの右のサブツリーを真新しいツリーと見なします。つまり、Dの右のサブツリーのルートノードHに入った後、考えずに左のサブツリーを歩くことができます。この図の二分木は比較的単純なので、Hは左のサブツリーがないので、Hの右のサブツリーを見てください。ない場合は、Dにフォールバックします。
④:Dの左右のサブツリーがなくなり、次のDにはトラバースされない子ノードがないため、1つのノードBでDに戻され、Bの右側のサブツリーが見つかり、ないことがわかりました。その後、Aに返されます。
⑤:Aは、サブツリーが経験してきた左、左に行くために、新しいツリーとして、Aの右部分木を右サブツリーを、最初の非脳は左のサブツリーを行って、その後、に戻った......
1.2グラフの深さ優先走査(DFS)
グラフについても同じことが言えます。ルートノードを取得したら、最初に前のノードがなくなるまでポールを挿入してから、前のノードに戻って別の分岐道路があるかどうかを確認します。ある場合は、他の分岐道路を処理します。真新しいグラフとしての分岐道路。行き来します。そうでない場合は、前のノードに戻って、道路に別の分岐があるかどうかを確認します。
違いは次のとおりです。
①:グラフがリングの場合があります。つまり、頭や尾がありません。したがって、最後にポールを挿入する過程で通過したノードに遭遇した場合は、のジャンクションに到達したことを意味します。頭と尾のリング、その後、前方に行く彼らがそう後退を開始、もはや前進していない、すべてトラバースされているノードです。
②:二分木のノードの場合、次のステップに進むとき、左のサブツリーと右のサブツリーの2つの選択肢しかなく、グラフには3つ、4つ、5つ、またはそれ以上のフォークがあります。したがって、各フォークが確実に渡されるように、whileループまたはforループを使用する必要があります。
グラフの深さ優先走査(DFS)は、次の図に示すとおりです。
最初に0-> 1-> 2-> 3-> 4-> 5の順序に従って、次の5が0、そしてそれは通過しました。それで、5に戻って、ウォークスルーされていない別のノードが5にあるかどうかを確認します。Gが見つかったので、Gは考えずにダウンします。
G-> Hの後、Hの次のノードもすべて渡されたことがわかったので、Gに戻って、渡されていない次のノードがあるかどうかを確認します。次のノードがない場合は、戻ります。までG - > F - > E - > D、それはDが持つことが判明した次のノードIた歩いていないので、私はに行くIを、
歩いた後、歩いていない次のノードがないことがわかったので、ルートノードに戻るまでフォールバックを続けました。D- > C-> B-> A、トラバーサル全体は以上。
2.コード
以下では、隣接リストに基づいた深さ優先走査(DFS)アルゴリズムを投稿します。その前に、隣接リストを簡単に紹介します。
以下に示すように、隣接テーブルはリンクリストノードの配列を使用してすべてのノードを格納し、リンクリストを使用して現在のノードに隣接するすべてのノードを格納します。
その中で、最初の行のABCDEFGHIは配列であり、配列タイプははListNode(リンクリストノード)です。次に、配列内の各要素は、上の図の隣接リストを構成する独自の隣接ポイントを指します。
上記の隣接テーブルの保存方法に基づいて、深さトラバーサルの手順は次のようになります。
このプログラムは、別のブログ投稿のプログラムを基にしています。
元のプログラムは次のとおりです。CSDNブロガーのブログ投稿データ構造[MistyRain Blurred Half World War] :グラフトラバーサル(1:深さ優先トラバーサル)
int visited[G_numVertexes];//用一个visited数组来记录某个节点是否被遍历过:1表示遍历过;0表示没有遍历过。其中 ,G_numVertexes是图中节点的个数,也是邻接表中第一行那个数组的元素个数
void DFSTraverse(ListNode *G) {
for (int i = 0; i < G_numVertexes; i++)
{
visited[i] = 0; //把visited数组的所有元素都初始化未0,表示都没遍历过
}
for (int i = 0; i < G_numVertexes; i++) //为了防止不连通图的特殊情况,在这里对每个节点都进行遍历
{
if (visited[i] == 0)
{
DFS(G, i); //对未遍历过的节点,调用DFS函数
}
}
}
void DFS(ListNode *G, int i) {
EdgeNode *p;
visited[i] = 1; //把这个节点的访问标志位设为1,表示已遍历过
cout << G[i]->data << endl; //打印当前节点
p = G[i]->adjvex; //根据邻接表的存储方式,把p设为G[i]的第一个邻接点
while (p)
{
cout << p->data << endl;
if (!visted[p->adjvex]) //如果G[i]的另一个邻接点未遍历过,则遍历它
{
DFS(G, p->adjvex); //递归访问
}
p = p->next;
}
}