Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 백엔드
- Swagger
- 인텔리제이
- DAO 연동 컨트롤러 서비스 설계
- 제로베이스
- spring
- MariaDB
- 제로베이스 #백엔드 #Java #Spring #개발자 #백엔드공부 #백엔드 스쿨
- 프로젝트 생성
- Java
- #devops #terraform #state
- validated
- 리포지토리 인터페이스
- 엔티티 설계
- 백엔드스쿨
- ORM
- 스프링부트실전가이드
- JPA
- 백엔드공부
- 스프링 부트 핵심 가이드
- DAO 설계
- auditing
- 개발자
- 유효성검사
- 데이터베이스 연동
Archives
- Today
- Total
JeongJin's Blog
균형 이진 탐색 트리 개념과 자바로 구현해보기 본문
1. 균형 이진 트리
- 모든 노드의 좌우 서브 트리 높이가 1이상 차이 나지 않는 트리
2. 이진 탐색 트리의 편향 발생
- Case 1) 이진 탐색 트리에 삽입되는 순서 : 20 → 10 → 30 → 5
- Case 2) 이진 탐색 트리에 삽입되는 순서 : 5 → 10 → 20 → 30
3. 균형 이진 탐색 트리
- Balanced Binary Search Tree
- 노드의 삽입과 삭제가 일어날 때 균형을 유지하도록 하는 트리
- 2번의 Case 2) 이 발생하지 않도록 한다.
- AVL 트리
- 노드가 삽입, 삭제될 때 트리의 균형을 체크하고 유지하는 트리
- 각 노드의 BF를 [-1,0,1] 만 가지게 하여 균형을 유지
- BF (Balance Factor) 란?
- 왼쪽 서브 트리 높이 - 오른쪽 서브 트리 높이
- BF (Balance Factor) 란?
- 리밸런싱
- 균형이 깨진 경우
- BF가 '+' 이면 왼쪽 서브 트리에 이상이 있음
- BF가 '-' 이면 오른쪽 서브 트리에 이상이 있음
- 회전 연산
- 단순 회전 - LL, RR
- 이중 회전 - LR, RL
- LL 트리란?
- Left - Left
- 회전 1회
- 오른쪽 방향으로 회전
- RR 트리란?
- Right - Right
- 회전 1회
- 왼쪽 방향으로 회전
- LR 이란?
- Left - Right
- 회전 2회
- RR 회전 후 LL 회전
- RL 이란?
- Right - Left
- 회전 2회
- LL 회전 후 RR 회전
- 균형이 깨진 경우
import java.util.LinkedList;
import java.util.Queue;
// 삽입
class Node {
int key;
int height;
Node left;
Node right;
public Node(int key, Node left, Node right) {
this.key = key;
this.height = 0;
this.left = left;
this.right = right;
}
}
class AVLTree {
Node head;
public int height(Node node) {
if (node == null) {
return -1;
}
return node.height;
}
// LL case
public Node rightRotate(Node node) {
Node lNode = node.left;
node.left = lNode.right;
lNode.right = node;
node.height = Math.max(height(node.left), height(node.right)) + 1;
lNode.height = Math.max(height(lNode.left), height(lNode.right)) + 1;
return lNode;
}
// RR case
public Node leftRotate(Node node) {
Node rNode = node.right;
node.right = rNode.left;
rNode.left = node;
node.height = Math.max(height(node.left), height(node.right)) + 1;
rNode.height = Math.max(height(rNode.left), height(rNode.right)) + 1;
return rNode;
}
// LR case
public Node lrRotate(Node node) {
node.left = leftRotate(node.left);
return rightRotate(node);
}
// RL case
public Node rlRotate(Node node) {
node.right = rightRotate(node.right);
return leftRotate(node);
}
public int getBalance(Node node) {
if (node == null) {
return 0;
}
return this.height(node.left) - this.height(node.right);
}
public void insert(int key) {
this.head = this.insert(this.head, key);
}
public Node insert(Node node, int key) {
if (node == null) {
return new Node(key, null, null);
}
// 삽입 진행
if (key < node.key) {
node.left = this.insert(node.left, key);
} else {
node.right = this.insert(node.right, key);
}
// 높이 갱신
node.height = Math.max(this.height(node.left), this.height(node.right)) + 1;
// 이상 여부 판단
int balance = this.getBalance(node);
// LL
if (balance > 1 && key < node.left.key) {
return this.rightRotate(node);
}
// RR
if (balance < -1 && key > node.right.key) {
return this.leftRotate(node);
}
// LR
if (balance > 1 && key > node.left.key) {
return this.lrRotate(node);
}
// RL
if (balance < -1 && key < node.right.key) {
return this.rlRotate(node);
}
return node;
}
public void levelOrder(Node node) {
Queue<Node> queue = new LinkedList<>();
queue.add(node);
while (!queue.isEmpty()) {
Node cur = queue.poll();
System.out.print(cur.key + " ");
if (cur.left != null) {
queue.offer(cur.left);
}
if (cur.right != null) {
queue.offer(cur.right);
}
}
System.out.println();
}
}
public class Practice1 {
public static void main(String[] args) {
AVLTree avl = new AVLTree();
// Insert
avl.insert(30);
avl.insert(20);
avl.insert(10); // LL
avl.levelOrder(avl.head);
avl.insert(40);
avl.insert(50); // RR
avl.levelOrder(avl.head);
avl.insert(5);
avl.insert(7); // LR
avl.levelOrder(avl.head);
avl.insert(60);
avl.insert(55); // RL
avl.levelOrder(avl.head);
}
}
/*
- 출력
20 10 30
20 10 40 30 50
20 7 40 5 10 30 50
20 7 40 5 10 30 55 50 60
*/
// 삭제
class AVLTree2 extends AVLTree {
public void delete(int key) {
this.head = delete(this.head, key);
}
public Node delete(Node node, int key) {
if (node == null) {
return null;
}
if (key < node.key) {
node.left = delete(node.left, key);
} else if (key > node.key) {
node.right = delete(node.right, key);
} else {
if (node.left == null) {
return node.right;
} else if (node.right == null) {
return node.left;
} else {
Node predecessor = node;
Node successor = node.left;
while (successor.right != null) {
predecessor = successor;
successor = successor.right;
}
predecessor.right = successor.left;
node.key = successor.key;
}
}
node.height = Math.max(this.height(node.left), this.height(node.right)) + 1;
int balance = this.getBalance(node);
// LL
if (balance > 1 && this.getBalance(node.left) > 0) {
return this.rightRotate(node);
}
// RR
if (balance < -1 && this.getBalance(node.right) < 0) {
return this.leftRotate(node);
}
// LR
if (balance > 1 && this.getBalance(node.left) < 0) {
return this.lrRotate(node);
}
// RL
if (balance < -1 && this.getBalance(node.right) > 0) {
return this.rlRotate(node);
}
return node;
}
}
public class Practice2 {
public static void main(String[] args) {
AVLTree2 avl = new AVLTree2();
avl.insert(30);
avl.insert(20);
avl.insert(40);
avl.insert(10);
avl.levelOrder(avl.head);
avl.delete(40);
avl.levelOrder(avl.head);
avl.insert(40);
avl.delete(10); // RR
avl.levelOrder(avl.head);
avl.insert(25);
avl.delete(40); // LR
avl.levelOrder(avl.head);
avl.insert(27);
avl.delete(20); // RL
avl.levelOrder(avl.head);
}
/*
- 출력
30 20 40 10
20 10 30
30 20 40
25 20 30
27 25 30
*/
}
'1일1공부 > 비선형자료구조' 카테고리의 다른 글
그래프의 개념과 자바로 구현해보기 (0) | 2023.09.26 |
---|---|
Red-Black 트리 개념 보기 (0) | 2023.09.22 |
이진 탐색 트리 개념과 자바로 구현해보기 (0) | 2023.09.20 |
트리의 개념과 자바로 구현해보기 (0) | 2023.09.15 |