익명 사용자
로그인하지 않음
토론
기여
계정 만들기
로그인
IT 위키
검색
AVL 트리
편집하기
IT 위키
이름공간
문서
토론
더 보기
더 보기
문서 행위
읽기
편집
원본 편집
역사
경고:
로그인하지 않았습니다. 편집을 하면 IP 주소가 공개되게 됩니다.
로그인
하거나
계정을 생성하면
편집자가 사용자 이름으로 기록되고, 다른 장점도 있습니다.
스팸 방지 검사입니다. 이것을 입력하지
마세요
!
고급
특수 문자
도움말
문단 제목
2단계
3단계
4단계
5단계
형식
넣기
라틴 문자
확장 라틴 문자
IPA 문자
기호
그리스 문자
그리스어 확장
키릴 문자
아랍 문자
아랍어 확장
히브리 문자
뱅골어
타밀어
텔루구어 문자
싱할라 문자
데바나가리어
구자라트 문자
태국어
라오어
크메르어
캐나다 원주민 언어
룬 문자
Á
á
À
à
Â
â
Ä
ä
Ã
ã
Ǎ
ǎ
Ā
ā
Ă
ă
Ą
ą
Å
å
Ć
ć
Ĉ
ĉ
Ç
ç
Č
č
Ċ
ċ
Đ
đ
Ď
ď
É
é
È
è
Ê
ê
Ë
ë
Ě
ě
Ē
ē
Ĕ
ĕ
Ė
ė
Ę
ę
Ĝ
ĝ
Ģ
ģ
Ğ
ğ
Ġ
ġ
Ĥ
ĥ
Ħ
ħ
Í
í
Ì
ì
Î
î
Ï
ï
Ĩ
ĩ
Ǐ
ǐ
Ī
ī
Ĭ
ĭ
İ
ı
Į
į
Ĵ
ĵ
Ķ
ķ
Ĺ
ĺ
Ļ
ļ
Ľ
ľ
Ł
ł
Ń
ń
Ñ
ñ
Ņ
ņ
Ň
ň
Ó
ó
Ò
ò
Ô
ô
Ö
ö
Õ
õ
Ǒ
ǒ
Ō
ō
Ŏ
ŏ
Ǫ
ǫ
Ő
ő
Ŕ
ŕ
Ŗ
ŗ
Ř
ř
Ś
ś
Ŝ
ŝ
Ş
ş
Š
š
Ș
ș
Ț
ț
Ť
ť
Ú
ú
Ù
ù
Û
û
Ü
ü
Ũ
ũ
Ů
ů
Ǔ
ǔ
Ū
ū
ǖ
ǘ
ǚ
ǜ
Ŭ
ŭ
Ų
ų
Ű
ű
Ŵ
ŵ
Ý
ý
Ŷ
ŷ
Ÿ
ÿ
Ȳ
ȳ
Ź
ź
Ž
ž
Ż
ż
Æ
æ
Ǣ
ǣ
Ø
ø
Œ
œ
ß
Ð
ð
Þ
þ
Ə
ə
서식 지정
링크
문단 제목
목록
파일
각주
토론
설명
입력하는 내용
문서에 나오는 결과
기울임꼴
''기울인 글씨''
기울인 글씨
굵게
'''굵은 글씨'''
굵은 글씨
굵고 기울인 글씨
'''''굵고 기울인 글씨'''''
굵고 기울인 글씨
[[분류:데이터베이스]][[분류:자료 구조]] ;Adelson-Velskii and Landis Tree ;트리내 각각의 노드마다 1 이하의 균형치(Balance Factor, +1,0,1)를 가지기 위해, 삽입과 삭제를 할때마다 균형치를 검사하여 RR, LL, LR, RL 회전연산을 시행하는 이진탐색트리 * 발표자인 1962년 G.M. Adelson-Velskii와 E.M. Landis 가 그들의 이름을 따서 명명 == 특징 == * 한 노드를 중심으로 좌우 종속 트리의 높이 차가 1 이하인 균형 잡힌 트리 * 이진 트리의 삽입·삭제 과정에서 한 방향으로 치우치거나, 높이 차이로 인해서 수행 시간이 증가되는 것을 막기 위해 균형 유지 * B 트리 등과 함께 균형잡힌 트리(height-balanced tree)라고도 불림 == 균형 인수 == 균형 인수(Balance Factor, BF)는 노드의 왼쪽 서브트리와 오른쪽 서브트리의 높이 차이를 의미한다. {| class="wikitable" |+균형 인수의 의미 !균형 인수 (BF)!!트리 상태 |- | -1, 0, 1||균형 상태 (Balanced) |- |< -1 또는 > 1||불균형 상태 (Unbalanced, 회전 필요) |} == 기본 동작 == 삽입 동작 * 기본적인 바이너리 트리의 삽입 동작과 동일하다 * 루트부터 대소관계를 따라가서 마지막 Leaf Node로 삽입이 된다. * 삽입 후 불균형이 생기면 리밸런싱 한다. '''삭제 동작''' * Leaf Node라면 그냥 삭제한다. * 자식 노드가 있다면 아래 두 가지 중 선택 가능하다. ** 오른쪽 서브트리에서 가장 작은 노드가 올라온다. '''(따로 정의된 바 없다면 이게 가장 기본)''' ** 왼쪽 서브트리에서 가장 큰 노드가 올라온다. * 삭제 후 불균형이 생기면 리밸런싱 한다. == 회전 동작 == '''헷갈릴 수 있으니 주의!''' 불균형 케이스와 회전 동작 간에 명칭이 상당히 헷갈릴 수 있다. 예를 들어 LL 케이스(Left-Left 불균형 케이스)에서는 Right Rotation이 일어난다. 불균형 케이스는 Left-Right, Left-Left, Right-Right와 같이 L과 R의 조합인데, 하필 Right Rotation, Left Rotation도 L과 R의 조합이라 "LL 회전"과 같이 혼란스러운 용어가 나오는 것이다. * LL 회전, RR 회전이라는 말은 없다. 이 말을 잘못 쓰는 경우는 아래와 같은 경우이다. ** Left 회전을 잘못 표기하는 경우 ** LL 케이스에서 이루어지는 회전을 줄여서 표기한 경우 (실제로는 이 경우 Right Roation이 일어난다.) * 아래 예시들에서 "개요"의 gif는 맞는 용어를 사용하고 있지만 그 아래 "동작 예시"엔 영어 그림상의 표기에 오류가 있으니 주의! === 개요 === [[파일:AVL Rotation.gif]] * L-L 케이스: A 로부터 N 까지의 경로상의 노드들을 오른쪽으로 회전 * L-R 케이스: A 로부터 N 까지의 경로상의 노드들을 왼쪽-오른쪽으로 회전 * R-L 케이스: A 로부터 N 까지의 경로상의 노드들을 오른쪽-왼쪽으로 회전 * R-R 케이스: A 로부터 N 까지의 경로상의 노드들을 왼쪽으로 회전 === 동작 예시 === * RR(Right-Right 케이스) - 왼쪽 회전(Left Rotation) ** 자식들이 오른쪽에 치우쳐 있을 때 왼쪽 회전이 일어난다. ** 왼쪽 회전이란 노드가 왼쪽(시계 반대 방향)으로 이동하는 경우이다. ** 또는 오른쪽의 자식이 왼쪽위의 루트로 올라오는 것이라고 생각할 수도 있다. * 아래 그림에서 LL Rotation이라는 말은 잘못되었다. 그냥 Left Rotation이라고 하는 게 맞다. [[파일:AVL LL Rotation.png|600px]] * LR(Left-Right 케이스) - 왼쪽 회전 후 [[파일:AVL LR Rotation.png|600px]] * RL 회전 [[파일:AVL RL Rotation.png|600px]] * LL 회전 [[파일:AVL RR Rotation.png|600px]] == 구현 코드 == === Python === <syntaxhighlight lang="python3"> class Node: def __init__(self, key): self.key = key self.left = None self.right = None self.height = 1 class AVLTree: def get_height(self, node): return node.height if node else 0 def get_balance(self, node): # 특정 노드를 기준으로 왼쪽 높이 - 오른쪽 높이를 반환한다. # 1보다 크면 왼쪽으로 과중된 것이고 -1보다 작으면 반대이다. # 노드가 없으면 0을 반환한다. return self.get_height(node.left) - self.get_height(node.right) if node else 0 def right_rotate(self, z): y = z.left T3 = y.right y.right = z z.left = T3 z.height = max(self.get_height(z.left), self.get_height(z.right)) + 1 y.height = max(self.get_height(y.left), self.get_height(y.right)) + 1 return y def left_rotate(self, z): y = z.right T2 = y.left y.left = z z.right = T2 z.height = max(self.get_height(z.left), self.get_height(z.right)) + 1 y.height = max(self.get_height(y.left), self.get_height(y.right)) + 1 return y def insert(self, root, key): if not root: return Node(key) # 재귀적으로 호출되다 위의 "root가 없는경우"까지 반복된다. if key < root.key: root.left = self.insert(root.left, key) else: root.right = self.insert(root.right, key) root.height = max(self.get_height(root.left), self.get_height(root.right)) + 1 balance = self.get_balance(root) if balance > 1 and key < root.left.key: return self.right_rotate(root) if balance < -1 and key > root.right.key: return self.left_rotate(root) if balance > 1 and key > root.left.key: root.left = self.left_rotate(root.left) return self.right_rotate(root) if balance < -1 and key < root.right.key: root.right = self.right_rotate(root.right) return self.left_rotate(root) return root def min_value_node(self, node): current = node while current.left: current = current.left return current def delete(self, root, key): if not root: return root if key < root.key: root.left = self.delete(root.left, key) elif key > root.key: root.right = self.delete(root.right, key) else: if not root.left: return root.right elif not root.right: return root.left temp = self.min_value_node(root.right) root.key = temp.key root.right = self.delete(root.right, temp.key) if not root: return root root.height = max(self.get_height(root.left), self.get_height(root.right)) + 1 balance = self.get_balance(root) if balance > 1 and self.get_balance(root.left) >= 0: return self.right_rotate(root) if balance > 1 and self.get_balance(root.left) < 0: root.left = self.left_rotate(root.left) return self.right_rotate(root) if balance < -1 and self.get_balance(root.right) <= 0: return self.left_rotate(root) if balance < -1 and self.get_balance(root.right) > 0: root.right = self.right_rotate(root.right) return self.left_rotate(root) return root def lookup(self, root, key): if not root or root.key == key: return root if key < root.key: return self.lookup(root.left, key) return self.lookup(root.right, key) def pre_order(self, root): if root: print(root.key, end=" ") self.pre_order(root.left) self.pre_order(root.right) # AVL 트리 테스트 avl = AVLTree() root = None for key in [10, 20, 30, 40, 50, 25]: root = avl.insert(root, key) print("Preorder traversal after insertions:") avl.pre_order(root) print("\n") # Lookup test search_key = 25 found_node = avl.lookup(root, search_key) print(f"Lookup {search_key}: {'Found' if found_node else 'Not found'}") # Deleting a node delete_key = 20 root = avl.delete(root, delete_key) print(f"\nPreorder traversal after deleting {delete_key}:") avl.pre_order(root) print("\n") </syntaxhighlight> == 같이 보기 == {{틀:데이터베이스 인덱스 트리}}
요약:
IT 위키에서의 모든 기여는 크리에이티브 커먼즈 저작자표시-비영리-동일조건변경허락 라이선스로 배포된다는 점을 유의해 주세요(자세한 내용에 대해서는
IT 위키:저작권
문서를 읽어주세요). 만약 여기에 동의하지 않는다면 문서를 저장하지 말아 주세요.
또한, 직접 작성했거나 퍼블릭 도메인과 같은 자유 문서에서 가져왔다는 것을 보증해야 합니다.
저작권이 있는 내용을 허가 없이 저장하지 마세요!
취소
편집 도움말
(새 창에서 열림)
틀:데이터베이스 인덱스 트리
(
편집
)
둘러보기
둘러보기
대문
최근 바뀜
광고
위키 도구
위키 도구
특수 문서 목록
문서 도구
문서 도구
사용자 문서 도구
더 보기
여기를 가리키는 문서
가리키는 글의 최근 바뀜
문서 정보
문서 기록