AVL 트리

컴퓨터 과학에서 AVL 트리(발명자의 이름인 Adelson-Velsky and Landis에서 따온 이름)는 자가 균형 이진 탐색 트리이다. 스스로 균형을 잡는 데이터 구조 중 처음으로 발명되었다. AVL 트리에서, 두 자식 서브트리의 높이는 항상 최대 1만큼 차이난다. 만약 어떤 시점에서 높이 차이가 1보다 커지면 이 속성을 유지하기 위해서 스스로 균형을 잡는다. 검색, 삽입, 삭제는 모두 평균과 최악의 경우 O(log n)의 시간복잡도가 걸린다. 삽입과 삭제는 한 번 이상의 트리 회전을 통해 균형을 잡을 수 있다. 높이 균형 성질(height-balance property): 트리 T {\displaystyle T} 의 모든 내부 노드(internal node) v {\displaystyle v} 에 대하여 v {\displaystyle v} 의 자식 노드들의 높이 차이가 최대 1이다. 임의의 이진 탐색 트리 T {\displaystyle T} 가 높이 균형 성질을 만족할 때 AVL 트리라고 한다. 높이 균형 성질(height-balance property)로부터 n {\displaystyle n} 개의 원소를 갖는 AVL 트리의 높이는 l o g n {\displaystyle logn} 이라는 사실을 알 수 있다. 이진 탐색 트리에서의 검색 시간복잡도는 트리의 높이 이므로 AVL 트리의 검색 시간이 O ( log ⁡ n ) {\displaystyle O(\log n)} 임을 알 수 있다. AVL 트리에서 노드를 일반적인 이진 탐색 트리처럼 삽입, 삭제 시키면 높이 균형 성질을 만족하지 않게 된다. 노드가 삽입, 삭제될 때 회전(rotation)을 통해 트리를 재구성하여 높이 균형 성질을 유지시킨다. AVL 트리 T에 새로운 노드 d를 삽입(Insertion)하는 방법은 T에서 d가 단말 노드(leaf node)로 삽입될 수 있도록 하는 노드 w를 찾고 w의 자식으로 d를 삽입한다. d를 삽입하면 불균형해질 수 있는데 세 노드를 기준으로 회전(rotation)시킴으로써 균형을 맞춘다. 트리 T {\displaystyle T} 의 재구성 작업을 회전(Rotation)이라 한다. 회전의 기준이 되는 세 노드 x {\displaystyle x} , y {\displaystyle y} , z {\displaystyle z} 는 다음과 같다. z {\displaystyle z} 는 w {\displaystyle w} 로부터 root로 가는 경로상에 가장 처음으로 위치한 불균형한 노드이다. y {\displaystyle y} 는 z {\displaystyle z} 의 자식 중에서 가장 큰 높이를 갖는 노드이다. x {\displaystyle x} 는 y {\displaystyle y} 의 자식 중에서 가장 큰 높이를 갖는 노드이다. x {\displaystyle x} 가 이진 탐색 트리 T {\displaystyle T} 의 노드이고 y {\displaystyle y} 가 부모, z {\displaystyle z} 가 할아버지 노드일 때 다음과 같이 재구성한다. x {\displaystyle x} , y {\displaystyle y} , z {\displaystyle z} 를 왼쪽-오른쪽 순서 (inorder)로 나열 한 순서대로 a {\displaystyle a} , b {\displaystyle b} , c {\displaystyle c} 라고 하고, x {\displaystyle x} , y {\displaystyle y} , z {\displaystyle z} 의 4개의 부분 트리들을 왼쪽-오른쪽 순서 (inorder)로 나열한 것을 T 0 {\displaystyle T_{0}} , T 1 {\displaystyle T_{1}} , T 2 {\displaystyle T_{2}} , T 3 {\displaystyle T_{3}} 라고 하자. z {\displaystyle z} 가 root인 부분 트리를 b {\displaystyle b} 를 root로 하는 새로운 부분 트리로 바꾼다. a {\displaystyle a} 가 b {\displaystyle b} 의 왼쪽 자식이 되고 T 0 {\displaystyle T_{0}} , T 1 {\displaystyle T_{1}} 은 각각 a {\displaystyle a} 의 왼쪽, 오른쪽 자식이 된다. c {\displaystyle c} 가 b {\displaystyle b} 의 오른쪽 자식이 되고, T 2 {\displaystyle T_{2}} , T 3 {\displaystyle T_{3}} 는 각각 c {\displaystyle c} 의 왼쪽, 오른쪽 자식이 된다. 이 작업을 구상화하면 b = y {\displaystyle b=y} 일 때 y {\displaystyle y} 를 z {\displaystyle z} 와 회전시키는 것처럼 보인다. 이 작업을 single rotation이라고 한다. b = x {\displaystyle b=x} 일 때 x {\displaystyle x} 를 y {\displaystyle y} 와 회전시키고 다시 z {\displaystyle z} 와 회전시키는 것처럼 보인다. 이 작업을 double rotation이라고 한다. 이 재구성 방법은 T {\displaystyle T} 의 부모-자식 관계만을 바꾸는 것이기 때문에 O ( 1 ) {\displaystyle O(1)} 시간이 걸린다. AVL 트리 T {\displaystyle T} 에서 노드 d {\displaystyle d} 를 삭제(Removal)하는 방법은 root부터 d {\displaystyle d} 를 검색한다. d {\displaystyle d} 가 단말 노드가 아니라면 자신의 왼쪽 부분 트리 중에서 최댓값을 갖는 노드나 오른쪽 부분 트리 중에서 최솟값을 갖는 노드를 d {\displaystyle d} 와 바꾼다. 이 작업을 d {\displaystyle d} 가 단말 노드가 될 때까지 반복하여 단말 노드 d {\displaystyle d} 를 삭제한다. 삭제 역시 트리가 불균형해질 수 있는데 삽입과 동일한 방법으로 d {\displaystyle d} 의 부모를 w {\displaystyle w} 라고 한 뒤 회전시켜 균형을 맞춘다. B 트리 Robert Lafore(1998), Data Structures & Algorithms in JAVA, Sams, ISBN 1-57169-095-6 Michael T.Goodrich, Roberto Tamassia(2006), Data Structures & Algorithms in JAVA(4th edition), John Wiley & Sons, ISBN 0-471-73884-0