공부/알고리즘 (c++)

BFS (Breadth First Search) 너비 우선 탐색

원클릭쓰리버그 2022. 1. 22. 16:48
728x90

BFS(너비 우선 탐색)

너비 우선 탐색은 넓게 탐색한다는 의미로 이해하면 편하다. 탐색의 경우 너무 보편적이고 코딩 테스트를 조금이라도 공부했다면 다 아는 내용이기 때문에 따로 설명은 하지 않겠다.

 

기존의 BFS를 구현할 때, 무식하게 구현하는 경우가 많았는데 역시 이 강의는 코드가 깔끔해서 좋다. 막 알고리즘을 배울때 무식하게 구현했던 나와는 다른 우아하고? 간단 명료한? 부럽다. 나도 저렇게 되야하는데...

 

#include <iostream>
#include <vector>
#include <queue>
using namespace std;

// DFS (Depth First Search) 깊이 우선 탐색
// 일단 갈 수 있는 방향0(깊이)을 가보고 탐색한다.
// BFS (Breadth First Search) 너비 우선 탐색
// 출발점에서 갈 수 있는 방향을 먼저 탐색 후 다음 방향을 설정한다.

struct Vertex
{
	//data
};

vector<Vertex> vertices;
vector<vector<int>> adjacent;
vector<bool> discoversd;
void CreateGraph()
{
	vertices.resize(6);
	adjacent = vector<vector<int>>(6);
	adjacent[0].push_back(1);
	adjacent[0].push_back(3);
	adjacent[1].push_back(0);
	adjacent[1].push_back(2);
	adjacent[1].push_back(3);
	adjacent[3].push_back(4);
	adjacent[5].push_back(4);
}

void Bfs(int here)
{
	//누구에 의해 발견 되었나?
	vector<int> parent(6, -1);
	//시작점에서 얼만큼 떨어져 있나?
	vector<int> distance(6, -1);

	queue<int> q;
	q.push(here);
	discoversd[here] = true;


	parent[here] = here;
	distance[here] = 0;

	while (q.empty() == false)
	{
		here = q.front();
		q.pop();

		cout << "Visited : " << here << endl;
		

		for (int there : adjacent[here])
		{
			if (discoversd[there])
				continue;

			q.push(there);
			discoversd[there] = true;

			parent[there] = here;
			distance[there] = distance[here] + 1;
		}
	}

	int i = 3;
}

void BfsAll()
{
	for (int i = 0; i < 6; i++)
		if (discoversd[i] == false)
			Bfs(i);
}
void CreateGraph2()
{
	vertices.resize(6);
	adjacent = vector<vector<int>>(6);

	adjacent = vector<vector<int>>
	{
		{0,1,0,1,0,0},
		{1,0,1,1,0,0},
		{0,0,0,0,0,0},
		{0,0,0,0,1,0},
		{0,0,0,0,0,0},
		{0,0,0,0,1,0},
	};
}
void Bfs2(int here)
{
	//누구에 의해 발견 되었나?
	vector<int> parent(6, -1);
	//시작점에서 얼만큼 떨어져 있나?
	vector<int> distance(6, -1);

	queue<int> q;
	q.push(here);
	discoversd[here] = true;


	parent[here] = here;
	distance[here] = 0;

	while (q.empty() == false)
	{
		here = q.front();
		q.pop();

		cout << "Visited : " << here << endl;


		for (int there = 0; there <6; there ++)
		{
			if (adjacent[here][there] == 0)
				continue;
			if (discoversd[there])
				continue;

			q.push(there);
			discoversd[there] = true;

			parent[there] = here;
			distance[there] = distance[here] + 1;
		}
	}

	int i = 3;
}

int main()
{
	CreateGraph();

	discoversd = vector<bool>(6, false);

	Bfs(0);
}

 

 

여기서 Parent와 distance가 가장 인상 깊었는데

 

distance를 보면 

출발 지점인 0번에서 2까지의 거리가 2번을 거쳐 가야한다는 것을 알 수 있어 최단 경로를 알 수 있게 해주는 방법을 저렇게 간단히 구현한다니..... 난 여지껏 최단거리를 구할 때, 어떤 짓을 한건지 ㅠㅠ

 

0번에서 2번을 가기 위해선 2개의 노드를 통해 가야한다. 그러면 어떻게 가는지에 대한 경로는 어디서 얻을 수 있을까?

여기 parent를 보면 도착점 2번은 1번, 1번은 0번을 통해 올 수 있다는 것을 확인할 수 있다. 그러므로 도착점 2는 출발점 0에서 거리는 2 distance이며, 경로는 0 -> 1-> 2 이다.  강의를 들으면 이런게 좋다. 시야가 넓어져.