[DFS_BFS]-1260_DFS와 BFS
인접행렬과 인접리스트를 사용하는 방법들 중 인접리스트를 이용하여 풀이 하였습니다.
인접행렬 인접리스트의 차이
인접행렬은 구현하기 매우 편리합니다. 노드의 연결관계를 알고 싶을때 adj[i][j]가 0인지 1인지 확인만 하면 되기 때문에 O(1)을 갖게 됩니다.(무방향에서는 0,0 | 1,1 | 2,2 ....| n.n 사이를 대각선을 두고 대칭을 이루게 됩니다. ) 하지만 정점이 어떤 한 노드에서 연결된 모든 노드를 방문 할 경우 adj[2]인 가로 행을 끝까지 돌아야 하므로 총 정점의 개수만큼 확인해보아야 하기 때문에 O(Vertax) 만큼 시간이 소요됩니다. 즉 정점이 많아짐에 따라 2차원 배열의 크기는 더욱 더 커지면서 많은 노드의 개수대로 확인을 해야하는 치명적인 문제가 발생합니다. 이러한 노드의 개수의 제약의 조금 더 효율적인 인접리스트 입니다. 노드가 1억개인데 간선이 10개도 안되는 경우, 이런경우 2차원 인접행렬을 쓰면 메모리 측면에서 비효율적인 측면을 갖게됩니다. 하지만 인접리스트는 해당 간선의 개수에 의존하여 생성되는 장점이자 단점을 가지고 있습니다. 즉 이말은 간선의 개수에 비례하여 메모리를 점유한다고 할 수 있습니다. 간선의 개수에 의존하므로 O(Edge)만큼의 시간복잡도를 가지고 있습니다. 이 부분이 장점이자 단점이 부분이였는데 단점인 부분을 보자면 i노드 j도가 연결되어 있는지 없는지 확인하려 할 때 인접행렬의 경우 adj[i][j] 로 바로 확인이 가능합니다(O(1)). 인접리스트의 경우 있는지 없는지 i번째 리스트에서 연결되있는 노드의 개수만큼 순회를 하는 단점을 가지게 됩니다.
package oneDay_twoSol.DB_FirstSearch;
import java.util.*;
public class DFS_BFS {
static ArrayList<ArrayList<Integer>> adjacentList = new ArrayList<>(); // 인접리스트
static boolean visited[]; // 방문 여부 판단.
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
int start_Vertax = sc.nextInt();
sc.nextLine();
for (int i = 0; i <= n; i++) {
adjacentList.add(new ArrayList<Integer>());
}
for (int i = 1; i <= m; i++) {
int a=sc.nextInt();
int b=sc.nextInt();
// 방향이 없는 그래프 특징.
adjacentList.get(a).add(b);
adjacentList.get(b).add(a);
}
for (int i = 1; i <=n; i++) {
if(!adjacentList.get(i).isEmpty())
Collections.sort(adjacentList.get(i));
}
/* for (int i = 0; i <adjacentList.size() ; i++) {
System.out.println(adjacentList.get(i));
}*/
visited=new boolean[n+1];
dfs(start_Vertax);
visited=new boolean[n+1];
System.out.println();
bfs(start_Vertax);
}
static void dfs(int vertax) {
System.out.print(vertax + " ");
visited[vertax] = true;
// ===== 방문함과 동시에 출력 =====
for (int i = 0; i <adjacentList.get(vertax).size() ; i++) {
//adjacentList.get(vertax) -> 해당 방문하는 노드의 인접리스트이 사이즈 만큼만 순회 (해당 정점과 연결되있는 노드만 탐색한다는 의미
int temp=adjacentList.get(vertax).get(i);
if (!visited[temp])
{ dfs(temp); // 재귀적으로 함수 호출을 하는 DFS의 특징
}
}
}
// 재귀적으로 호출하는 성질인 DFS와는 다르게 큐의 삽입된 정점들을 차례대로 상대하는 특징을 가지므로 재귀적인 DFS와는 다른 특징.
static void bfs(int vertax)
{
Queue<Integer> q=new LinkedList<>();
q.offer(vertax);
visited[vertax]=true;
while (!q.isEmpty())
{
int temp=q.poll();
System.out.print(temp+" ");
for (int i = 0; i <adjacentList.get(temp).size() ; i++) {
int v=adjacentList.get(temp).get(i);
if(!visited[v])
{
q.offer(v);
visited[v]=true;
}
}
}
}
}
Author And Source
이 문제에 관하여([DFS_BFS]-1260_DFS와 BFS), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@admin1194/DFSBFS-1260DFS와-BFS저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)