Search
moon
sun

그래프

그래프(Graph)

정의: 정점(Vertex)과 간선(Edge)들의 유한 집합으로, 정점들 사이의 연결 관계를 표현하는 자료구조. N:N 관계를 표현하는데 용이하며 100점짜리 자료구조임.

핵심 요소

구성 요소
설명
정점 (Vertex/Node)
데이터가 저장되는 위치
간선 (Edge)
정점 간의 연결을 나타내는 선
인접 (Adjacent)
두 정점이 간선으로 직접 연결된 상태
차수 (Degree)
하나의 정점에 연결된 간선의 수

그래프 탐색

•
너비 우선 탐색 - BFS
•
깊이 우선 탐색 - DFS

너비 우선 탐색 - BFS

import java.util.LinkedList; import java.util.Queue; import java.util.Scanner; /* (입력예시) 1 7 6 1 7 1 2 2 4 2 5 1 3 3 6 6 7 (그래프 예시) 1 / \ 2 3 / \ \ 4 5 6 | 7 */ public class bfs_Samplecode { static int T, N, M, A, B; // 정점을 담을 큐 (row, col, cost) static Queue<Integer> que = new LinkedList<Integer>(); // 출발지 S, 목적지 E static int S, E; // 인접 행렬 static int MAT[][] = new int[101][101]; static int visited[] = new int[101]; // 방문 횟수 static int cnt = 0; public static void bfs() { // 1. 시작점을 큐에 넣는다. que.add(S); visited[S] = 1; cnt++; // 5. 큐가 비어있는지 않다면 반복 while(!que.isEmpty()) { // 2. 큐에서 한 점을 꺼내서 기준점으로 삼는다. System.out.println("now : " + que.peek()); int now = que.poll(); // 3. 기준점이 목적지이면 탐색을 종료한다. if( now == E ) break; // 4. 그렇지 않은 경우 기준점에서 갈 수 있는 다른 정점들을 큐에 넣는다. else { for (int i = 1; i <= N; i++) { // 기존에 방문하지 않고 // 현재 정점과 연결된 점을 탐색 if( visited[i] == 0 && MAT[now][i] == 1 ) { visited[i] = 1; cnt++; // 해당 지점을 큐에 넣는다. que.add(i); System.out.println(i + "번 정점 방문"); } } } } } public static void main(String[] args) { Scanner sc = new Scanner(System.in); T = sc.nextInt(); for (int test_case = 1; test_case <= T; test_case++) { // N : 정점의 수 // M : 간선의 수 N = sc.nextInt(); M = sc.nextInt(); // S : 출발지 // E : 목적지 S = sc.nextInt(); E = sc.nextInt(); // visited배열 초기화 for (int i = 1; i <= N; i++) { visited[i] = 0; } // 인접배열 초기화 for (int i = 1; i <= N; i++) { for (int j = 1; j <= M; j++) { MAT[i][j] = 0; } } // 인접배열 정점간의 관계 지정 for (int i = 1; i <= M; i++) { A = sc.nextInt(); B = sc.nextInt(); MAT[A][B] = 1; } // 인접배열 출력 for (int i = 1; i <= N; i++) { for (int j = 1; j <= N; j++) { System.out.print(MAT[i][j] + " "); } System.out.println(); } // 그래프 탐색 - BFS(Breadth First Search) bfs(); System.out.println(cnt + "개의 정점 방문"); } } }
Java
복사

깊이 우선 탐색 - DFS

import java.util.Scanner; /* 깊이 우선 탐색(Depth First Search, DFS) - 깊이 우선탐색은 트리나 그래프를 탐색하는 알고리즘 중 하나로, 한 정점에서 출발하여 가능한 멀리까지 탐색하는 방법이다. - dfs는 지나온 경로를 쉽게 파악할 수 있는 장점이 있으며, 스택(Stakc) 이나 재귀함수(Recursion Func)로 구현할 수 있다. (입력예시) 1 6 5 1 2 2 3 2 4 1 5 5 6 (그래프 예시) 1 / \ 2 5 / \ \ 3 4 6 */ public class dfs_Samplecode { static int T, N, M, A, B; // i번째 정점을 방문했는지 여부를 체크할 배열 // i번째 정점을 방문(O) visited[i] = 1 // i번째 정점을 방문(x) visited[i] = 0 static int visited[] = new int[101]; // 인접 배열 static int MAT[][] = new int[101][101]; // 방문 횟수 static int cnt = 0; // void dfs(int idx, int depth) // - idx : 현재위치, depth : 깊이 2가지를 기본적인 인자로 가진다. public static void dfs(int idx, int depth) { System.out.println("depth: " + depth); // 종료조건 if( idx == N ) { } // 탐색조건 else { for (int i = 1; i <= N; i++) { // 기존에 방문한 정점이 아니고 // 현재 정점과 연결된 정점인 경우에만 탐색 if( visited[i] == 0 && MAT[idx][i] == 1 ) { // i번째 정점을 방문 System.out.println(i + "번 정점 방문 " ); cnt++; visited[i] = 1; dfs(i, depth+1); // 탐색이 끝나면 해제 System.out.println(i + "번으로 돌아옴"); visited[i] = 0; } } } } public static void main(String[] args) { Scanner sc = new Scanner(System.in); T = sc.nextInt(); for (int test_case = 1; test_case <= T; test_case++) { // N : 정점의 수 // M : 간선의 수 N = sc.nextInt(); M = sc.nextInt(); // visisted배열 초기화 for (int i = 0; i < N; i++) { visited[i] = 0; } // 인접배열 초기화 for (int i = 1; i <= N; i++) { for (int j = 1; j <= N; j++) { MAT[i][j] = 0; } } // 인접배열 정점간의 관계 지정 for (int i = 1; i <= M; i++) { A = sc.nextInt(); B = sc.nextInt(); MAT[A][B] = 1; } // 인접배열 출력 for (int i = 1; i <= N; i++) { for (int j = 1; j <= M; j++) { System.out.print(MAT[i][j] + " "); } System.out.println(); } // 그래프 탐색 - DFS(Depth First Search) dfs(1, 1); // root(+1) 포함 정점 방문 수 System.out.println(cnt+1 + "개의 정점 방문"); } } }
Java
복사

Java로 구현한 기본 그래프 예시

public class Graph { private int V; // 정점의 개수 private LinkedList<Integer>[] adj; // 인접 리스트 // 그래프 생성자 public Graph(int v) { V = v; adj = new LinkedList[v]; for (int i = 0; i < v; ++i) adj[i] = new LinkedList(); } // 간선 추가 public void addEdge(int v, int w) { adj[v].add(w); adj[w].add(v); // 무방향 그래프의 경우 } }
Java
복사

Java Collections를 활용한 그래프 구현

import java.util.*; public class GraphWithCollections { private Map<Integer, List<Integer>> adjacencyList; public GraphWithCollections() { adjacencyList = new HashMap<>(); } // 정점 추가 public void addVertex(int vertex) { adjacencyList.putIfAbsent(vertex, new ArrayList<>()); } // 간선 추가 public void addEdge(int source, int destination) { // 정점이 없다면 추가 adjacencyList.putIfAbsent(source, new ArrayList<>()); adjacencyList.putIfAbsent(destination, new ArrayList<>()); // 양방향 간선 추가 adjacencyList.get(source).add(destination); adjacencyList.get(destination).add(source); } // 인접 정점 가져오기 public List<Integer> getAdjVertices(int vertex) { return adjacencyList.get(vertex); } }
Java
복사