22. 이진 검색 트리
22.1 도입
- 검색 트리(search tree) 는 연결 리스트, 큐 처럼 자료들을 담는 컨테이너지만, 자료들을 일정한 순서에 따라 정렬한 상태로 저장합니다.- 주어진 순서에 따라 자료들을 저장하는 리스트와 큐와는 다른 속성
- 이러한 특성을 이용해, 추가, 삭제, 존재 여부 확인 등 다양한 연산을 빠르게 수행
 
- 검색 트리에서 가장 흔하게 사용하는 것이 이진 검색 트리(binary search tree)와 그 변종들 이다.
22.2 이진 검색 트리의 정의와 조작
22.2.1 정의
- 이진 트리(binary tree): 각 노드가 왼쪽, 오른쪽 최대 두 개의 자식 노드만을 가질 수 있는 트리 - 자식 노드들의 배열 대신 두개의 포인터 left, right를 담는 객체로 구현
 
- 이진 검색 트리는 이진 탐색에서 아이디어를 가져와서 만든 트리이다. - 우리가 N개의 원소 중에서 원하는 값을 찾는데, 매번 후보의 수를 절반씩 줄여갈 수 있다면 O(logN) 시간에 그 값을 찾을 수 있다. 
- 이진 검색 트리의 각 노드는 하나의 원소(value)를 가지고 있다. 
- 왼쪽 서브 트리에는 해당 노드의 원소보다 작은 원소를 가진 노드들 
- 오른쪽 서브 트리에는 보다 큰 원소를 가진 노드들이 들어간다. 
 
22.2.2 순회
- 이진 검색 트리는 중위 순회를 하면 크기 순서로 정렬된 원소의 목록을 얻을 수 있다.- 집합에 포함된 최대 원소나 최소 원소를 쉽게 얻을 수 있다는 의미
- 왼쪽 연결로 쭉 내려갔을 때 만나는 노드:- 최소 원소,- 가장 일찍 출력되는 노드
- 오른쪽 연결로 쭉 내려갔을 때 만나는 노드:- 최대 원소,- 가장 마지막에 출력되는 노드
 
22.2.3 자료의 검색
- 한 번 원소를 비교하는 것 만으로도 찾아야 할 전체 대상의 절반을 줄일 수 있다.- 실질적으로 이진 탐색과 비슷한 속도를 자료를 찾을 수 있다.
 
22.2.4 조작 (추가, 삭제)
- 추가, 삽입 - 선형적인 구조의 제약이 없기 때문에, 새 원소가 들어갈 위치를 찾고, 거기에 노드를 추가하기만 하면 간단히 가능
- 추가, 삽입은 새 리프(잎) 노드가 생길 뿐이므로, 트리 전체의 구조에는 영향이 없음
 
- 삭제 - 삭제는 트리 어디서든 일어날 수 있어, 트리 전체의 구조에 영향을 주므로 여럽다. 
- 간단한 방법: - '합치기'연산을 구현- 노드 t를 지울 거라면, t의 두 서브트리를 합친 새로운 트리를 만든 뒤, 이 트리를 t를 루트로 하는 서브트리와 바꿔치기
  
 
22.2.5 X보다 작은 원소의 수 찾기 / k번째 원소 찾기
- 표준 라이브러리에서 지원하는 언어는 거의 없기 때문에, 이 연산을 사용하려면, 직접 이진 검색 트리를 구현할 수 밖에 없다.- 실제 구현은 트립의 구현을 다루는 22.6절 을 참고
 
- 실제 구현은 
22.3 시간 복잡도 분석과 균형 잡힙 이진 검색 트리
- 이진 검색 트리에 대한 모든 연산은 모두 루트에서 부터 한 단계씩 트리를 내려가며 재귀 호출을 통해 수행된다.- 최대 재귀 호출의 횟수는 트리의 높이 h와 같다.
- 따라서 모든 연산의 시간 복잡도가 트리의 높이 O(h)라 할 수 있다.
 
- 이진 검색 트리의 높이는 자료들이 어떤 순서로 추가, 삭제되느냐에 따라 다르다.- 극단적인 경우 한쪽으로만 노드가 있어서 기울어진(skewed) 트리가 될 수도 있다. (연결리스트와 다를 게 없다)
- 우리가 원하는 이상적인 경우는 가로로 넓게 퍼지고 ‘평평한’ 트리 이다.
- 트리의 높이가 1 높아질 때마다 트리에 들어갈 수 있는 원속의 수가 대략 두 배 늘어간다
- 트리의 최소 높이(h)는 O(logN)이다
 
- 균형 잡힌 이진 검색 트리 (balanced binary search tree)- 이진 검색 트리의 변종, 기울어짐 방지
- 트리의 구조에 추가적인 제약을 둠, 이 제약을 만족되도록 노드들을 옮김
- 트리의 높이가 항상 O(logN)이 되도록 유지
- 대표적인 예시: 레드-블랙(red-black) 트리, AVL 트리
- 이진 검색 트리의 구현도 내부적으로는 레드-블랙(red-black) 트리을 사용한다.
 
22.6 균형 잡힙 이진 검색 트리 직접 구현하기: 트립
- 대부분의 균형 잡힌 이진 검색 트리들(AVL 트리, 레드-블랙 트리) 은 구현이 매우 까다롭다.- 코드가 길고, 한정된 시간 안에 코드를 작성해야하는 프로그래밍 대회에서 사용하기 부적합
- 따라서, 구현이 간단한 이진 검색 트리를 사용: 트립(treap, tree+heap)
 
22.6.1 트립의 정의
- 트립은 입력이 특정 순서로 주어질 때 그 성능이 떨어진다는 이진 검색 트리의 단점을 해결하기 위해 고안된 랜덤화된 이진 검색 트리이다.
- 트립은 원소들의 추가 순서에 따라 결정되지 않고, 난수에 의해 임의로 결정된다.- 어느 순서대로 추가, 삭제 되더라도, 트리 높이의 기대치는 항상 일정하다.
 
- 이 속성을 위해서, 트립은 새 노드가 추가될 때 마다 해당 노드에 우선순위(priority) 를 부여한다.- 우선순위 값은 난수 이다.
 
- 트립을 이해하는 또 다른 방법: 노드들을 우선순위가 높은 것부터 순서대로 추가한 이진 검색 트리
트립의 조건 2가지
- 이진 검색 트리의 조건 - 왼쪽 서브 트리에는 해당 노드의 원소보다 작은 원소를 가진 노드들 
- 오른쪽 서브 트리에는 보다 큰 원소를 가진 노드들이 들어간다. 
 
- 힙의 조건: 모든 노드의 우선순위는 각자의 자식 노드보다 크거나 같다. 
Reference
- 프로그래밍 대회에서 배우는 알고리즘 문제 해결 전략 (구종만, 인사이트)
- https://www.algospot.com/