코딩 테스트
트리
조요피
2023. 2. 21. 20:54
트리(Tree)는 노드와 에지로 연결된 그래프의 특수한 형태.
- 순환 구조(Cycle)가 없다. 1개의 루트만 존재한다.
- 루트 노드를 제외한 노드는 단 1개의 부모 노드만 갖는다.
- 트리의 부분 트리(Subtree) 역시 트리의 모든 특징을 따른다.
트리의 구성 요소
- 노드
- 데이터의 index와 value를 표현하는 요소
- 에지
- 노드와 노드의 연결 관계를 나타내는 선
- 루트 노드
- 트리에서 가장 상위에 존재하는 노드
- 부모 노드
- 두 노드 사이의 관계에서 상위 노드에 해당하는 노드
- 자식 노드
- 두 노드 사이의 관계에서 하위 노드에 해당하는 노드
- 리프 노드
- 트리에서 가장 하위에 존재하는 노드(자식 노드가 없는 노드)
- 서브 트리
- 전체 트리에 속한 작은 트리
// https://www.acmicpc.net/problem/11725
import java.util.ArrayList;
import java.util.Scanner;
import java.util.Stack;
public class Main {
static ArrayList<Integer>[] alArr;
static int[] arr;
static boolean[] visited;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt() + 1;
alArr = new ArrayList[n];
for (int i = 0; i < n; i++) {
alArr[i] = new ArrayList<>();
}
for (int i = 0; i < n - 2; i++) {
int a = sc.nextInt();
int b = sc.nextInt();
alArr[a].add(b);
alArr[b].add(a); // 방향이 없기 때문에 양방향 모두 저장
}
arr = new int[n];
visited = new boolean[n];
DFS(1);
for (int i = 2; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
private static void DFS(int root) {
Stack<Integer> s = new Stack<>();
s.add(root);
while (s.isEmpty() == false) {
int node = s.pop();
if (visited[node] == false) {
visited[node] = true;
for (int n :
alArr[node]) {
if (visited[n] == false) {
s.add(n);
arr[n] = node;
}
}
}
}
}
}
트라이
트라이(Trie)는 문자열 검색을 빠르게 실행할 수 있도록 설계한 트리 형태의 자료구조.
트라이는 일반적으로 단어들을 사전의 형태로 생성한 후 트리의 부모 자식 노드 관계를 이용해 검색을 수행.
- N진 트리
- 문자 종류의 개수에 따라 N이 결정.
- 예를 들어 알파벳은 26개의 문자로 이뤄져 있으므로 26진 트리로 구성된다.
- 루트 노드는 항상 빈 문자열을 뜻하는 공백 상태를 유지
// https://www.acmicpc.net/problem/14425
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
Node root = new Node();
// 트라이 자료구조 생성
while (n-- > 0) {
String text = sc.next();
Node node = root;
for (int i = 0; i < text.length(); i++) {
char c = text.charAt(i);
if (node.next[c - 'a'] == null) {
node.next[c - 'a'] = new Node();
}
node = node.next[c - 'a'];
if (i == text.length() - 1) node.isEnd = true; // 마지막 문자 체크
}
}
// 트라이 자료구조 검색
int count = 0;
while(m-- > 0) {
String text = sc.next();
Node node = root;
for (int i = 0; i < text.length(); i++) {
char c = text.charAt(i);
if (node.next[c - 'a'] == null) break;
node = node.next[c - 'a'];
if(i == text.length() -1 && node.isEnd) count++; // 마지막 문자 일치 확인
}
}
System.out.println(count);
}
}
class Node {
Node[] next = new Node[26];
boolean isEnd;
}
이진 트리
이진 트리(Binary tree)는 각 노드의 자식 노드(차수)의 개수가 2 이하로 구성돼 있는 트리를 말한다.
트리 영역에서 가장 많이 사용되는 형태.
- 평향 이진 트리
- 노드들이 한쪽으로 편향돼 생성된 이진 트리
- 포화 이진 트리
- 트리의 높이가 모두 일정하며 리프 노드가 꽉찬 이진 트리
- 완전 이진 트리
- 마지막 레벨을 제외하고 완전하게 노드들이 채워져 있고, 마지막 레벨은 왼쪽부터 채워진 트리
데이터를 트리 자료구조에 저장할 때 편향 이진트리의 형태로 저장하면 탐색 속도가 저하되고 공간이 낭비된다.
일반적으로 코딩 테스트에서 데이터를 트리에 담는다고 하면 완전 이진트리 형태.
가장 직관적이면서 편리한 트리 자료구조 형태는 '배열'
이동 목표 노드 (index) | 인덱스 연산 | 제약 조건(N = 노드 개수) |
루트 노드 | index = 1 | |
부모 노드 | index = index / 2 | 현재 노드가 루트 노드가 아님 |
왼쪽 자식 노드 | index = index * 2 | index * 2 <= N |
오른쪽 자식 노드 | index = index * 2 + 1 | index * 2 + 1 <= N |
import java.util.Scanner;
public class Main {
static int[][] arr = new int[26][2];
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
arr = new int[26][2]; // 알파벳 전체 길이, 좌우 저장
for (int i = 0; i < n; i++) {
int node = sc.next().charAt(0) - 'A'; // 인덱스로 관리
int left = sc.next().charAt(0);
int right = sc.next().charAt(0);
if (left == '.') arr[node][0] = -1; // 값이 없으면 -1
else arr[node][0] = left - 'A';
if (right == '.') arr[node][1] = -1;
else arr[node][1] = right - 'A';
}
preOrder(0); // 루트부터 시작
System.out.println();
inOrder(0);
System.out.println();
postOrder(0);
}
/**
* 전위 순회
*
* @param now
*/
private static void preOrder(int now) {
if (now == -1) return;
System.out.print((char) (now + 'A'));
preOrder(arr[now][0]);
preOrder(arr[now][1]);
}
/**
* 중위 순회 *
*
* @param now
*/
private static void inOrder(int now) {
if (now == -1) return;
inOrder(arr[now][0]);
System.out.print((char) (now + 'A'));
inOrder(arr[now][1]);
}
/**
* 후위 순회 *
*
* @param now
*/
private static void postOrder(int now) {
if (now == -1) return;
postOrder(arr[now][0]);
postOrder(arr[now][1]);
System.out.print((char) (now + 'A'));
}
}
세그먼트 트리
주어진 데이터들의 구간 합과 데이터 업데이트를 빠르게 수행하기 위해 고안해낸 자료구조의 형태.
더 큰 범위는 '인덱스 트리'라고 하는데 코딩 테스트 영역에서는 큰 차이가 없다.
- 세그먼트 트리의 종류
- 구간 합
- 최대 / 최소 구하기
- 구현 단계
- 트리 초기화
- 질의 값 구하기 (구간 합 또는 최대 / 최소)
- 데이터 업데이트
*어려워서 pass, 나중에 다시 보자
최소 공통 조상
*어려워서 pass, 나중에 다시 보자