グラフィックアルゴリズム-グラフィック遍歴/検索:DFS、BFS


💡 グラフィックの遍歴/検索


  • グラフィック内の任意の頂点から、すべての頂点に1つずつアクセスする操作.

  • グラフィック巡回またはグラフィックブラウズ.

  • 典型的な方法は深さ優先ナビゲーション(DFS)と幅優先ナビゲーション(BFS)である.
  • 💡 深度優先ナビゲーション


  • サブノードを優先的に参照する方法.

  • できるだけ深く入り込んで、どこにも行けない場合は、前の頂点に戻るようにグラフィックを巡回します.

  • スタックで実現します.

  • ノードにアクセスしたかどうかを確認する必要があります.
  • 01.DFSプロセス


  • aノード(開始ノード)にアクセスします.
  • がアクセスしたノードは、アクセスしたことを示す.
  • aノードに隣接するノードが順次巡回する.
    aに隣接するノードがない場合、終了します.
  • aおよび隣接ノードbにアクセスしている場合は、aに隣接する別のノードにアクセスする前に、bのすべての隣接ノードにアクセスする必要があります.
  • bを起点としてDFSを再起動し、Bの隣接ノードにアクセスする.
  • bのすべてのブランチを完璧に探索すれば、再びaに近い頂点にはまだアクセスされていない頂点が見つかった.
  • bブランチを全面的にナビゲートした後でのみ、aの他の隣接ノードにアクセスできます.
  • まだアクセスしていない頂点であれば、終了します.存在する場合、DFSは頂点から再開されます.
  • 02.DFS利用

  • Spanning Tree, Connected Component, Strongly Connected Component
  • 9000 DFSコード

    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    void dfs(int root, bool*visit, vector<vector<int>> node, vector<int> &res) {
    
    	// root 노드 방문
    	if (visit[root] == true) {
    		return;		// 방문한 경우, 바로 빠져나옴.
    	}
    
    	visit[root] = true;	// 방문한 노드 표시
    	res.push_back(root);
    	//cout << root << " ";
    
    	for (int i = 0; i < node[root].size(); i++) {	// root 노드와 인접한 정점을 모두 방문
    		int x = node[root][i];
    		dfs(x, visit, node, res);
    	}
    }
    
    void print(vector<vector<int>> node) {
    	for (int i = 0; i < node.size(); i++) {
    		for (int j = 0; j < node[i].size(); j++) {
    			cout << node[i][j] << " ";
    		}
    		cout << endl;
    	}
    }
    
    int main() {
    	int n;	// node 개수
    	n = 10;
    	bool *visit = new bool[n];
    	vector<vector<int>> node(n);
    	vector<int> res;
    	
    	//1과 2연결
    	node[1].push_back(2);
    	node[2].push_back(1);
    
    	// 1과 3을 연결 
    	node[1].push_back(3); 
    	node[3].push_back(1); 
    	
    	// 2과 3을 연결 
    	node[2].push_back(3); 
    	node[3].push_back(2); 
    	
    	// 2와 4를 연결 
    	node[2].push_back(4); 
    	node[4].push_back(2); 
    	
    	// 2와 5를 연결 
    	node[2].push_back(5); 
    	node[5].push_back(2); 
    	
    	// 4와 8을 연결 
    	node[4].push_back(8); 
    	node[8].push_back(4); 
    	
    	// 5와 9를 연결 
    	node[5].push_back(9); 
    	node[9].push_back(5); 
    	
    	// 3과 6을 연결 
    	node[3].push_back(6); 
    	node[6].push_back(3); 
    	
    	// 3과 7을 연결 
    	node[3].push_back(7); 
    	node[7].push_back(3);
    
    	//print(node);
    
    	// 1번 node부터 dfs 탐색 실행
    	dfs(1, visit, node, res);
    
    	for (int i = 0; i < res.size(); i++) {
    		cout << res[i] << " ";
    	}
    	cout << endl;
    
    	return 0;
    }

    💡 幅優先ナビゲーション


  • 兄弟ノードを優先的に探索する方法.

  • 以前ノード(親ノード)にアクセスしていなかった隣接ノード(現在のノードの兄弟ノード)を優先的に参照

  • レベル遍歴(level-order遍歴).

  • キューで実現します.

  • ノードにアクセスしたかどうかを確認する必要があります.
  • 01.BFSプロセス


  • 開始ノードにアクセスします.(アクセスしたノードを確認)
  • キューにアクセスするノード(enqueue)を挿入します.
  • 初期状態のキューには、開始ノードのみが格納されます.
  • の開始ノードのすべての隣接ノードにアクセスし、隣接する隣接ノードにアクセスします.
  • キューから取り出されたすべてのノードと隣接ノードに順次アクセスします.
  • キューから取り出したノードにアクセスします.
  • キューから取り出されたすべてのノードと隣接ノードにアクセスします.
    隣接ノード
  • がない場合、ノード
  • がキューの前面から取り出される.
  • キューでアクセスするノード(enqueue)を挿入します.
  • キューが枯渇するまで続行します.
  • 02.BFS利用

  • 最短経路ナビゲーション、生成ツリー、接続コンポーネント、シリアル接続コンポーネント
  • .

    ΄BFSコード

    #include <iostream>
    #include <queue>
    #include <vector>
    
    using namespace std;
    
    
    void bfs(int start, vector<vector<int>> arr, vector<bool> visit, vector<int>& res) {
    	queue<int> q;
    	q.push(start);
    	visit[start] = true;
    
    	while (!q.empty()) {
    		// 큐에 값이 있는 경우 = 아직 방문하지 않은 노드 존재
    		int x = q.front();
    		q.pop();
    		//cout << x << " ";
    		res.push_back(x);
    
    		for (int i = 0; i < arr[x].size(); i++) {
    			int y = arr[x][i];
    
    			if (!visit[y]) {
    				
    				q.push(y);
    
    				visit[y] = true;
    			}
    		}
    	}
    }
    
    void print(vector<vector<int>> node) {
    	for (int i = 0; i < node.size(); i++) {
    		for (int j = 0; j < node[i].size(); j++) {
    			cout << node[i][j] << " ";
    		}
    		cout << endl;
    	}
    }
    
    int main() {
    	int n;	// node 개수
    	n = 10;
    	vector<vector<int>> arr(n);
    	vector<bool> visit(n, 0);
    	vector<int> res;
    
    	// 1과 2를 연결 
    	arr[1].push_back(2); 
    	arr[2].push_back(1); 
    	
    	// 1과 3을 연결 
    	arr[1].push_back(3); 
    	arr[3].push_back(1); 
    	
    	// 2와 4를 연결 
    	arr[2].push_back(4); 
    	arr[4].push_back(2); 
    	
    	// 2와 5를 연결 
    	arr[2].push_back(5); 
    	arr[5].push_back(2); 
    	
    	// 4와 8을 연결 
    	arr[4].push_back(8); 
    	arr[8].push_back(4); 
    	
    	// 5와 9를 연결 
    	arr[5].push_back(9); 
    	arr[9].push_back(5); 
    	
    	// 3과 6을 연결 
    	arr[3].push_back(6); 
    	arr[6].push_back(3); 
    	
    	// 3과 7을 연결 
    	arr[3].push_back(7); 
    	arr[7].push_back(3);
    
    	//print(arr);
    
    	// 1번 node부터 bfs 실행
    	bfs(1, arr, visit, res);
    
    	for (int i = 0; i < res.size(); i++) {
    		cout << res[i] << " ";
    	}
    	cout << endl;
    
    	return 0;
    }

    コード#コード#

  • https://github.com/arittung/Study/tree/main/algorithm
  • リファレンス

  • https://gamedevlog.tistory.com/32
  • https://gmlwjd9405.github.io/2018/08/15/algorithm-bfs.html
  • https://gmlwjd9405.github.io/2018/08/14/algorithm-dfs.html
  • https://hongku.tistory.com/157