완전 이진트리(Complete Binary Tree)
완전이진트리
1) 완전 이진트리는 마지막 레벨을 제외 하고 모든 레벨이 완전히 채워져 있다.
2) 마지막 레벨은 꽉 차 있지 않아도 되지만, 노드가 왼쪽에서 오른쪽으로 채워져야 한다.
3) 마지막 레벨 h에서 1~2h-1 개의 노드를 가질 수 있다.
4) 완전 이진 트리는 배열을 사용해 효율적으로 표현 가능하다.
전 이진트리(Full Binary Tree)
전이진트리
1) 전 이진트리는 모든 노드가 0개 또는 2개의 자식 노드를 갖는 트리이다.
포화 이진트리(Perfect Binary Tree)
1) 포화 이진트리는 모든 레벨이 노드로 꽉 차 있는 트리를 뜻한다.
2) 전 이진트리의 성질도 만족해야 한다. 즉 모든 노드가 0개 혹은 2개의 자식 노드를 갖는다.
3) 모든 말단 노드가 동일한 깊이 또는 레벨을 갖는다.
4) 트리의 노드 개수가 정확히 2^k-1 개여야 한다. 여기서 k는 트리의 높이다.
자료(key)의 중복을 허용하지 않음
왼쪽 자식 노드는 부모 노드보다 작은 값, 오른쪽 자식 노드는 부모 노드보다 큰 값을 가짐
자료를 검색에 걸리는 시간이 평균 log(n) 임
inorder traversal 탐색을 하게 되면 자료가 정렬되어 출력됨
트리순회
전위 순회 (Preorder Traversal)
전위 순회는 깊이 우선 순회(DFT, Depth-First Traversal)이라고도 합니다.
트리를 복사하거나, 전위 표기법을 구하는데 주로 사용됩니다.
트리를 복사할때 전위 순회를 사용하는 이유는 트리를 생성할 때 자식 노드보다 부모 노드가 먼저 생성되어야 하기 때문입니다.
전위 순회는 다음과 같은 방법으로 진행합니다.
- Root 노드를 방문한다.
- 왼쪽 서브 트리를 전위 순회한다.
- 오른쪽 서브 트리를 전위 순회한다.
Preorder Traversal
위 트리에 전위 순회 결과는 다음과 같습니다.
A→B→D→E→C→F→G
중위 순회 (Inorder Traversal)
중위 순회는 왼쪽 오른쪽 대칭 순서로 순회를 하기때문에 대칭 순회(symmetric traversal)라고도 합니다.
중위 순회는 이진 탐색트리(BST)에서 오름차순 또는 내림차순으로 값을 가져올 때 사용됩니다.
내림차순으로 값을 가져오기 위해서는 역순(오른쪽-> root-> 왼쪽)으로 중위 순회를 하면 됩니다.
중위 순회는 다음과 같은 방법으로 진행합니다.
- 왼쪽 서브 트리를 중위 순회한다.
- Root 노드를 방문한다.
- 오른쪽 서브 트리를 중위 순회한다.
Inorder Traversal
위 트리에 중위 순회 결과는 다음과 같습니다.
D→B→E→A→F→C→G
후위 순회 (Postorder Traversal)
후위 순회는 트리를 삭제하는데 주로 사용됩니다.
이유는 부모노드를 삭제하기 전에 자식 노드를 삭제하는 순으로 노드를 삭제해야 하기 때문입니다.
후위 순회는 다음과 같은 방법으로 진행합니다.
- 왼쪽 서브 트리를 후위 순회한다.
- 오른쪽 서브 트리를 후위 순회한다.
- Root 노드를 방문한다.
Postorder Traversal
위 트리에 중위 순회 결과는 다음과 같습니다.
D→E→B→F→G→C→A
코드로 표현
1. node
class TreeNode {
int value;
TreeNode left;
TreeNode right;
// Constructor
public TreeNode(int value) {
this.value = value;
this.left = null;
this.right = null;
}
}
public class BinaryTree {
TreeNode root;
public BinaryTree() {
root = null;
}
// 추가적인 메소드들 (삽입, 삭제, 탐색 등)
}
2. array
class BinaryTreeArray {
int[] tree;
int size;
public BinaryTreeArray(int capacity) {
tree = new int[capacity];
size = 0;
}
// 인덱스를 기반으로 트리의 왼쪽 자식, 오른쪽 자식 접근
public int leftChild(int i) {
return 2 * i + 1;
}
public int rightChild(int i) {
return 2 * i + 2;
}
public void addNode(int value) {
if (size < tree.length) {
tree[size++] = value;
}
}
}
그래프 (Graph)
: 정점과 간선들의 유한 집합 G = (V,E)
정점(vertex) : 여러 특성을 가지는 객체, 노드(node)
간선(edge) : 이 객체들을 연결 관계를 나타냄. 링크(link)
간선은 방향성이 있는 경우와 없는 경우가 있음
그래프를 구현하는 방법 : 인접 행렬(adjacency matrix), 인접 리스트(adjacency list)
그래프를 탐색하는 방법 : BFS(bread first search), DFS(depth first search)
그래프의 예)
코드로 표현
1. 비방형 그래프
import java.util.*;
class Graph {
// 각 노드의 연결을 저장하는 맵
private Map<Integer, List<Integer>> adjList;
// 그래프 초기화
public Graph() {
adjList = new HashMap<>();
}
// 그래프에 노드 추가
public void addNode(int node) {
adjList.putIfAbsent(node, new ArrayList<>());
}
// 간선 추가 (비방향 그래프)
public void addEdge(int node1, int node2) {
adjList.putIfAbsent(node1, new ArrayList<>());
adjList.putIfAbsent(node2, new ArrayList<>());
adjList.get(node1).add(node2);
adjList.get(node2).add(node1); // 비방향 그래프이므로 양쪽에 간선 추가
}
// 그래프 출력 (인접 리스트 형식)
public void printGraph() {
for (int node : adjList.keySet()) {
System.out.print(node + " -> ");
for (int neighbor : adjList.get(node)) {
System.out.print(neighbor + " ");
}
System.out.println();
}
}
}
public class UndirectedGraphExample {
public static void main(String[] args) {
Graph graph = new Graph();
// 노드 추가
graph.addNode(1);
graph.addNode(2);
graph.addNode(3);
graph.addNode(4);
// 간선 추가
graph.addEdge(1, 2);
graph.addEdge(1, 3);
graph.addEdge(2, 4);
// 그래프 출력
graph.printGraph();
}
}
2. 방향그래프
public class DirectedGraphArray {
private int[][] adjMatrix;
// 그래프 초기화
public DirectedGraphArray(int size) {
adjMatrix = new int[size][size]; // 크기 `size`인 인접 행렬 초기화
}
// 간선 추가 (방향 그래프)
public void addEdge(int node1, int node2) {
adjMatrix[node1][node2] = 1; // 단방향 그래프이므로 한쪽 방향만 추가
}
// 그래프 출력
public void printGraph() {
for (int i = 0; i < adjMatrix.length; i++) {
System.out.print(i + " -> ");
for (int j = 0; j < adjMatrix[i].length; j++) {
if (adjMatrix[i][j] == 1) {
System.out.print(j + " ");
}
}
System.out.println();
}
}
public static void main(String[] args) {
// 노드 5개로 그래프 생성
DirectedGraphArray graph = new DirectedGraphArray(5);
// 간선 추가
graph.addEdge(0, 1);
graph.addEdge(0, 2);
graph.addEdge(1, 3);
graph.addEdge(2, 4);
// 그래프 출력
graph.printGraph();
}
}
3. 가중치그래프
public class WeightedGraphArray {
private int[][] adjMatrix;
// 그래프 초기화
public WeightedGraphArray(int size) {
adjMatrix = new int[size][size]; // 크기 `size`인 인접 행렬 초기화
// 기본값을 -1로 설정하여 가중치가 없음을 표시 (0이면 가중치가 없는 간선이 되므로 -1 사용)
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
adjMatrix[i][j] = -1;
}
}
}
// 간선 추가 (가중치 포함)
public void addEdge(int node1, int node2, int weight) {
adjMatrix[node1][node2] = weight; // 간선 추가
}
// 그래프 출력
public void printGraph() {
for (int i = 0; i < adjMatrix.length; i++) {
System.out.print(i + " -> ");
for (int j = 0; j < adjMatrix[i].length; j++) {
if (adjMatrix[i][j] != -1) {
System.out.print("[" + j + ", " + adjMatrix[i][j] + "] ");
}
}
System.out.println();
}
}
public static void main(String[] args) {
// 노드 5개로 그래프 생성
WeightedGraphArray graph = new WeightedGraphArray(5);
// 간선 추가 (가중치 포함)
graph.addEdge(0, 1, 10);
graph.addEdge(0, 2, 5);
graph.addEdge(1, 3, 2);
graph.addEdge(2, 4, 3);
// 그래프 출력
graph.printGraph();
}
}
해싱
: 검색을 위한 자료 구조
키(key)에 대한 자료를 검색하기 위한 사전(dictionary) 개념의 자료 구조
key는 유일하고 이에 대한 value를 쌍으로 저장
index = h(key) : 해시 함수가 key에 대한 인덱스를 반환해줌 해당 인덱스 위치에 자료를 저장하거나 검색하게 됨
해시 함수에 의해 인덱스 연산이 산술적으로 가능 O(1)
저장되는 메모리 구조를 해시테이블이라 함
jdk 클래스 : HashMap, Properties
두 가지방식 모두 찾아봐야함
https://codechacha.com/ko/java-system-identityhashcode/
https://yoongrammer.tistory.com/70
'Algorithm' 카테고리의 다른 글
파스칼의 삼각형 (1) | 2024.12.13 |
---|---|
이진트리탐색 - 전위, 중위, 후위 (0) | 2024.12.13 |
깊이 우선 탐색 - DFS(Depth-First Search) - dijkstra 다익스트라 (0) | 2024.12.13 |
넓이우선탐색 BFS(Breadth-First Search) (0) | 2024.12.13 |
에라토스테네스 체 (소수찾기) (0) | 2024.12.13 |