이진 탐색 트리란?
이진탐색트리(Binary Search Tree; BST)는 정렬된 tree이다.
어느 노드를 선택하든 해당 노드의 왼쪽 서브 트리에는 그 노드의 값보다 작은 값들을 지닌 노드들로만 이루어져 있고, 오른쪽 서브 트리에는 그 노드의 값보다 큰 값들을 지닌 노드들로만 이루어져 있는 이진 트리이다. 서브 트리도 재귀적으로 이러한 조건을 만족한다.
1. 각 노드에 중복되지 않는 키(key)가 있다.
2. 루트노드의 왼쪽 서브 트리는 해당 노드의 키보다 작은 키를 갖는 노드들로 이루어져 있다.
3. 루트노드의 오른쪽 서브 트리는 해당 노드의 키보다 큰 키를 갖는 노드들로 이루어져 있다.
4. 좌우 서브 트리도 모두 이진 탐색 트리여야 한다.
특징
기존 이진트리보다 탐색이 빠르다. 이진 탐색 트리의 탐색 연산은 트리의 높이(height)가 h라면 O(h)의 시간 복잡도를 갖는다. 노드의 개수가 n이라면 높이만큼 O(logn)의 시간복잡도를 갖는다. 이러한 효율적인 탐색이 가능한 이유는 탐색 과정 속에 있다.
탐색
1. 루트 노드의 키와 찾고자 하는 값을 비교한다. 찾고자 하는 값이라면 탐색을 종료한다.
2. 찾고자 하는 값이 루트 노드의 키보다 작다면 왼쪽 서브 트리로 탐색을 진행한다.
3. 찾고자 하는 값이 루트노드의 키보다 크다면 오른쪽 서브트리로 탐색을 진행한다.
위 과정을 찾고자 하는 값을 찾을 때까지 반복해서 진행한다. 만약 값을 찾지 못한다면 그대로 종료한다. 이러한 탐색 과정을 거치면 최대 트리의 높이(h)만큼의 탐색이 진행되게 된다.
위와 같은 트리에서 키가 5인 노드를 찾고자 한다면, 가장 먼저 루트 노드와의 비교가 이루어진다.
5<7이므로 왼쪽 서브 트리로의 탐색이 이루어지고, 이후 5>3이므로 오른쪽 서브트리로 탐색이 이루어진다. 마지막으로 키가 5인 노드를 찾았으므로 탐색이 종료된다. 즉 트리의 높이인 3번 만큼의 탐색이 이루어졌다. 만약 8을 찾는다면 2번의 연산이 진행되었을 것이다. 즉, 트리 안의 값을 찾는다면 무조건 트리의 높이(h) 이하의 탐색이 이루어지게 된다.
트리 안에 찾고자 하는 값이 없더라도 최대 h번 만큼만의 탐색이 진행된다. 예를 들어 위 트리에서 6이라는 값을 찾는다고 하면 위 그림과 같은 과정을 거치고 탐색이 종료된다. 마지막으로 탐색하게 되는 5를 키로 갖는 노드에서 6>5이므로 오른쪽 서브트리로 탐색을 진행해야 하는데 오른쪽 서브 트리가 없으므로 탐색이 종료되는 것이다.
삽입
이진 탐색 트리는 저장과 동시에 정렬을 하는 자료구조로 새로운 데이터를 저장할 때 위에서 언급한 이진 탐색 트리의 조건에 맞도록 일정한 규칙에 따라 저장을 하게 된다.
1. 삽입할 값을 루트 노드와 비교해 같다면 오류를 발생한다. ( 중복 값 허용 X )
2. 삽입할 값이 루트 노드의 키보다 작다면 왼쪽 서브 트리를 탐색해서 비어있다면 추가하고, 비어있지 않다면 다시 값을 비교한다.
3. 삽입할 값이 루트노드의 키보다 크다면 오른쪽 서브트리를 탐색해서 비어있다면 추가하고, 비어있지 않다면 다시 값을 비교한다.
아래와 같은 트리에 6을 키로 가진 노드를 추가해보자.
탐색과 비슷하게 삽입하고자 하는 값을 계속해서 비교해서 삽입할 위치를 찾는다.
삽입할 위치가 5의 오른쪽 서브 트리인 것을 찾았으므로, 5의 오른쪽 자식으로 6을 추가하면 된다.
삭제
이진탐색트리의 삭제는 삽입보다 조금 더 복잡하다. 이진 탐색 트리에서 특정 노드를 삭제할 때 아래와 같은 3가지 상황을 나누어 구현해야 한다.
1. 삭제하려는 노드가 단말 노드(leaf node) 일 경우
자식이 없는 단말 노드의 삭제는 간단하다. 삭제할 노드의 부모 노드가 있다면 부모 노드의 자식 노드를 NULL로 만들고, 삭제할 노드를 삭제(메모리 해제) 해주면 된다.
2. 삭제하려는 노드의 서브 트리가 하나인 경우(왼쪽 혹은 오른쪽 서브 트리)
삭제하려는 노드의 서브 트리가 하나인 경우도 간단하다. 삭제할 노드의 자식노드를 삭제할 노드의 부모노드가 가리키게 하고 해당 노드를 삭제하면 된다.
3. 삭제하려는 노드의 서브 트리가 두 개인 경우
삭제하려는 노드의 서브트리가 두 개인 경우는 가장 복잡하다. 이 경우 두 가지 방법을 사용할 수 있다.
1) 삭제할 노드 왼쪽 서브 트리의 가장 큰 자손을 해당 노드의 자리에 올린다.
위와 같이 삭제할 노드의 왼쪽 서브 트리에서 가장 큰 자손을 해당 노드의 자리에 올리면, 이진 탐색 트리의 조건을 만족하면서 트리가 유지되는 것을 확인할 수 있다. 또한 자리를 옮기면서 다른 노드들(4번노드)도 자리가 적절히 이동한 것을 확인 할 수 있다.
2) 삭제할 노드 오른쪽 서브 트리의 가장 작은 자손을 해당 노드의 자리에 올린다.
위와 같이 삭제할 노드의 오른쪽 서브 트리에서 가장 작은 자손을 해당 노드의 자리에 올리면, 이진 탐색 트리의 조건을 만족하면서 트리가 유지되는 것을 확인할 수 있다. 또한 자리를 옮기면서 다른 노드들(10번노드)도 자리가 적절히 이동한 것을 확인 할 수 있다.
시간복잡도
검색과 저장, 삭제의 시간복잡도는 모두 O(logn)이고, 최악의 경우는 한쪽으로 치우친 tree가 되었을 때로 Linked List와 다를 바가 없어지는 경우로 O(n)이다.
자가 균형 이진 탐색 트리(Self-Balancing BST)
알고리즘으로 이진 트리의 균형이 잘 맞도록 유지하여 높이를 가능한 낮게 유지하는 이진 탐색 트리로 시간 복잡도가 O(n)이 되는 최악의 경우를 해결할 수 있는 방식이다.
대표적으로 AVL tree와 Red-black tree가 있다.
AVL 트리 - 성질/삽입방법/활용
탄생 계기 이진탐색트리는 위 그림과 같이 한쪽으로 노드가 쏠릴 수가 있는 문제점이 있다. 10,9,8,7,6을 순서대로 삽입한다고 생각해보면 저런 형태의 트리가 만들어진다는 것을 알 수 있을 것이
hyolls100.tistory.com
RB(Red-Black) 트리 - 성질/삽입방법/활용
탄생 계기 이진탐색트리는 위 그림과 같이 한쪽으로 노드가 쏠릴 수가 있는 문제점이 있다. 10,9,8,7,6을 순서대로 삽입한다고 생각해보면 저런 형태의 트리가 만들어진다는 것을 알 수 있을 것이
hyolls100.tistory.com
'CS 공부 > 자료구조' 카테고리의 다른 글
RB(Red-Black) 트리 - 성질/삽입방법/활용 (0) | 2023.08.11 |
---|---|
AVL 트리 - 성질/삽입방법/활용 (0) | 2023.08.10 |
트리(Tree)의 순회 (전위/중위/후위 순회) (0) | 2023.08.10 |
여러 종류의 트리(Tree) 정리 (이진 트리, 전 이진 트리, 완전 이진 트리, 포화 이진 트리, 이진 탐색 트리) (0) | 2023.08.09 |
힙(Heap)이란? (0) | 2023.08.09 |