반응형
그래프
- 선형 자료구조나 트리 자료구조로 표현하기 어려운 N:M 관계를 가지는 원소를 표현하는데 용이
- 정점 (Vertex) : 그래프의 구성요소로 하나의 연결점
- 간선 (Edge) : 두 정점을 연결하는 선
- 차수 (Degree) : 정점에 연결된 간서의 수
- 양방향 그래프 (최대 V * (V-1) / 2 개의 간선)
- 단반향 그래프 (최대 V * (V-1) 개의 간선)
인접 행렬
- 두 정점을 연결하는 간선의 유무를 행렬로 표현
- V x V 정방 행렬
- 행번호와 열 번호는 그래프의 정점에 대응
- 두 정점이 인접되어 있으면(또는 가중치) 1 그렇지 않으면 0으로 표현
- 무향 그래프 : i번째 행의 합 = i번째 열의 합 = Vi의 차수
- 유향 그래프 : 행 i의 합 = Vi의 진출 차수, 열 i의 합 = Vi의 진입 차수
희소 그래프 vs 완전 그래프
- 희소 그래프는 정점에 비해 간선이 적어 인접행렬을 사용하면 메모리 낭비가 발생할 수 있다.
- 완전 그래프는 정점에 비해 간선이 많으므로 인접행렬을 사용하면 효율적이다.
import java.util.Arrays;
import java.util.Scanner;
/*
7
8
0 1
0 2
1 3
1 4
2 4
3 5
4 5
5 6
*/
public class AdjMatrixTest {
static int N;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
N = sc.nextInt(); // 정점 수
int C = sc.nextInt(); // 간선 수
int[][] adjMatrix = new int[N][N];
for (int i = 0; i < C; i++) {
int from = sc.nextInt();
int to = sc.nextInt();
adjMatrix[from][to] = adjMatrix[to][from] = 1;
}
for (int[] is : adjMatrix) {
System.out.println(Arrays.toString(is));
}
}
}
인접 리스트
- 각 정점에 대한 인접 정점들을 순차적으로 표현
- 하나의 정점에 대한 인접 정점들을 각각 노드로 하는 연결리스트로 저장
- 비순차적 탐색 처리가 느리다는 단점이 있다.
import java.util.Scanner;
/*
7
8
0 1
0 2
1 3
1 4
2 4
3 5
4 5
5 6
*/
public class AdjListTest {
static class Node {
int vertex;
Node link;
public Node(int vertex, Node link) {
this.vertex = vertex;
this.link = link;
}
@Override
public String toString() {
return "Node{" +
"vertex=" + vertex +
", link=" + link +
'}';
}
}
static int N;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
N = sc.nextInt(); // 정점 수
int C = sc.nextInt(); // 간선 수
Node[] adjList = new Node[N];
for (int i = 0; i < C; i++) {
int from = sc.nextInt();
int to = sc.nextInt();
adjList[from] = new Node(to, adjList[from]);
adjList[to] = new Node(from, adjList[to]);
}
for (Node head : adjList) {
System.out.println(head);
}
}
}
간선 리스트
- 두 정점에 대한 간선 그 자체를 객체로 표현하여 리스트로 저장
- 간선을 표현하는 두 정점의 정보를 나타냄 (시작, 끝 정점)
BFS
- 트리에서는 부모와 자식간의 관계가 명확하므로 방문관리하지 않지만, 그래프에서는 한 정점에서의 경로가 다양할 수 있으므로 방문관리를 해야된다.
- 시작 정점을 큐에 삽입하고, 방문하지 않은 곳이라면 큐에 넣고 방문한 것으로 표시
인접 행렬 BFS
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
public class AdjMatrixTest {
static int N;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
N = sc.nextInt(); // 정점 수
int C = sc.nextInt(); // 간선 수
int[][] adjMatrix = new int[N][N];
for (int i = 0; i < C; i++) {
int from = sc.nextInt();
int to = sc.nextInt();
adjMatrix[from][to] = adjMatrix[to][from] = 1;
}
bfs(adjMatrix, 0);
}
public static void bfs(int[][] adjMatrix, int start) {
Queue<Integer> queue = new LinkedList<>();
boolean[] visited = new boolean[N];
queue.offer(start);
visited[start] = true;
while (!queue.isEmpty()) {
int current = queue.poll();
System.out.println(current);
// current 정점의 인접정점 처리 (단, 방문하지 않은 인접정정만)
for (int j = 0; j < N; j++) {
if (!visited[j] && adjMatrix[current][j] != 0) {
queue.offer(j);
visited[j] = true;
}
}
}
}
}
인접 리스트 BFS
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
public class AdjListTest {
static class Node {
int vertex;
Node link;
public Node(int vertex, Node link) {
this.vertex = vertex;
this.link = link;
}
@Override
public String toString() {
return "Node{" +
"vertex=" + vertex +
", link=" + link +
'}';
}
}
static int N;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
N = sc.nextInt(); // 정점 수
int C = sc.nextInt(); // 간선 수
Node[] adjList = new Node[N];
for (int i = 0; i < C; i++) {
int from = sc.nextInt();
int to = sc.nextInt();
adjList[from] = new Node(to, adjList[from]);
adjList[to] = new Node(from, adjList[to]);
}
bfs(adjList, 0);
}
public static void bfs(Node[] adjList, int start) {
Queue<Integer> queue = new LinkedList<>();
boolean[] visited = new boolean[N];
queue.offer(start);
visited[start] = true;
while (!queue.isEmpty()) {
int current = queue.poll();
System.out.println(current);
for (Node temp = adjList[current]; temp != null; temp = temp.link) {
if (!visited[temp.vertex]) {
queue.offer(temp.vertex);
visited[temp.vertex] = true;
}
}
}
}
}
DFS
인접 행렬 DFS
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
public class AdjMatrixTest {
static int N;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
N = sc.nextInt(); // 정점 수
int C = sc.nextInt(); // 간선 수
int[][] adjMatrix = new int[N][N];
for (int i = 0; i < C; i++) {
int from = sc.nextInt();
int to = sc.nextInt();
adjMatrix[from][to] = adjMatrix[to][from] = 1;
}
dfs(adjMatrix, new boolean[N], 0);
}
public static void dfs(int[][] adjMatrix, boolean[] visited, int current) {
visited[current] = true;
System.out.println(current);
for (int j = 0; j < N; j++) {
if (!visited[j] && adjMatrix[current][j] != 0) {
dfs(adjMatrix, visited, j);
}
}
}
}
인접 리스트 DFS
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
public class AdjListTest {
static class Node {
int vertex;
Node link;
public Node(int vertex, Node link) {
this.vertex = vertex;
this.link = link;
}
@Override
public String toString() {
return "Node{" +
"vertex=" + vertex +
", link=" + link +
'}';
}
}
static int N;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
N = sc.nextInt(); // 정점 수
int C = sc.nextInt(); // 간선 수
Node[] adjList = new Node[N];
for (int i = 0; i < C; i++) {
int from = sc.nextInt();
int to = sc.nextInt();
adjList[from] = new Node(to, adjList[from]);
adjList[to] = new Node(from, adjList[to]);
}
dfs(adjList, new boolean[N], 0);
}
public static void dfs(Node[] adjList, boolean[] visited, int current) {
visited[current] = true;
System.out.println(current);
for (Node temp = adjList[current]; temp != null; temp = temp.link) {
if (!visited[temp.vertex]) {
dfs(adjList, visited, temp.vertex);
}
}
}
}
반응형