[이진 검색 트리의 개념]
: 각 노드를 객체로 하는 연결 데이터 구조
# 노드의 구성
- key 값 영역
- 부속 데이터
- Left : 왼쪽 자식노드 포인터 (자식노드 없으면 NIL)
- Right : 오른쪽 자식노드 포인터 (자식노드 없으면 NIL)
- Parent : 부모노드 포인터 (노드가 root면 NIL)
[이진 검색 트리 특성]
x가 이진 검색트리의 한 노드이고, y가 x의 왼쪽 서브트리의 한 노드일때, y.key <= x.key 를 만족한다. ( 오른쪽일때는 y.key >= x.key 만족 ) |
[이진 검색 트리의 연산]
- 종류 : SEARCH, MINIMUM, MAXIMUM, PREDECESSOR, SUCCESSOR, INSERT, DELETE
- 연산 평균 시간 복잡도 : Θ(logn)
- 최악 시간 복잡도 : Θ(n) : 노드들이 선형일때(한쪽으로만 쏠려을때)
[이진 검색 트리 순회 방식]
1. 중위 트리 순회 : left, root, right
2. 전위 트리 순회 : root, left, right
3. 후위 트리 순회 : left, right, root
# 중위 트리 순회 의사코드
INORDER-TREE-WALK(x) if x != NIL INORDER-TREE-WALK(x.left) print x.key INORDER-TREE-WALK(x.right) |
: 내부의 3문장의 순서의 위치를 바꿈으로써 전위, 중위, 후위 방식으로 변경할 수 있다.
[이진 검색 트리 검색]
# 재귀 방식의 검색 의사코드
TREE_SEARCH(x, k) if x == NIL or k == x.key return x if k < x.key return TREE-SEARCH(x.left, k) else return TREE-SEARCH(x.right, k) |
: 검색한 key값 나올때까지 key값 기준 오른쪽 or 왼쪽으로 내려가 재귀적으로 검색.
# 순환 방식의 검색 의사코드
ITERATIVE-TREE-SEARCH(x, k) while x != NIL and k != x.key if k < x.key x = x.left else x = x.right return x |
[최소 최대 원소 찾기]
: 이진 검색트리에서 최소값, 최대값을 찾는 방식 (O(logn))
# 최소 원소 찾기
TREE-MINIMUM(x) while left[x] != NIL do x <- left[x] return x |
: 이진 검색 트리 특성상, 최소값은 트리의 왼쪽 최하단에 위치해 있다.
# 최대 원소 찾기
TREE-MAXIMUM(x) while x.right != NIL x = x.right return x |
: 이진 검색 트리 특성상, 최대값은 트리의 오른쪽 최한단에 위치해 있다.
[직후원소(Successor) 찾기]
: 이진 검색 트리내에서 크기 기준 다음 노드를 찾는다. (2가지 상황으로 나뉜다)
case1. 원소 x의 오른쪽 자식 노드가 있을때
: 원소 x보다 다음으로 큰 노드는 오른쪽 자식 트리중 가장 왼쪽에 있는 원소 이다.
case2. 원소 x의 오른쪽 자식 노드가 없을때
: 현재 노드가 왼쪽 자식 노드일때까지 트리를 올라간다. 그때의 부모노드가 다음으로 큰 노드이다.
: 만약 해당되는 경우가 없으면, 현재 원소 x가 트리내의 최대값 원소이다.
# 직후원소 검색 의사 코드
TREE-SUCCESSOR(x) if x.right != NIL # case 1 then return TREE-MINIMUM(x.right) y = x.p # case 2 (x.p = x.parent) while y != NIL and x == y.right x = y y = y.p return y |
[직전원소(Predecessor) 찾기]
: 직후원소 찾는 방식과 유사
원소 x의 왼쪽 자식 노드가 있을때 case1.
: 원소 x보다 다음으로 큰 노드는 왼쪽 자식 트리중 가장 오른쪽에 있는 원소 이다.
원소 x의 오른쪽 자식 노드가 없을때 case2.
: 만약 해당되는 경우가 없으면, 현재 원소 x가 트리내의 최소값 원소이다.
# 직전원소 의사코드 생략
[삽입(Insertion)]
: 값 v를 이진 검색 트리의 알맞은 위치에 삽입 (비교적 간단)
: 값 v에 해당되는 자식 NIL 위치에 삽입하면 된다.
# 이진트리 삽입 의사코드
TREE-INSERT(T, z) # 이진트리 T에 값 z 삽입 y = NIL # y는 현재 노드, x는 다음 비교 노드 x = T.root
while x != NIL # 알맞은 잎 노드위치로 이동 y = x if z.key < x.key x = x.left else x = x.right
z.p = y # y가 알맞은 잎노드인 상황 (x은 NIL), 주어진 노드 z의 parent에 y 저장 if y == NIL # 트리 T가 빈 트리일때 T.root = z
elseif z.key < y.key # 마지막으로 주어진 z와 y값 비교해 잎노드의 왼쪽 or 오른쪽 자식에 z 노드 삽입 y.left = z else y.right = z |
[삭제(Deletion)] **
: 주어진 노드 값 z를 이진 검색 트리에서 삭제
case1. 원소 z가 자식 노드가 없을때
: 노드 z의 부모 노드의 z 포인터를 NIL 변경해주기만 하면 된다
case2. 원소 z가 한개의 자식 노드를 가지고 있을때
: 노드 z의 부모 노드의 z 포인터를 z 노드의 자식 노드로 변경해주기만 하면 된다
case3. 원소 z가 두개의 자식 노드를 가지고 있을때
: 노드 z의 직후원소(Succesor) y를 찾고, y가 z의 자리를 차지하도록 한다.
(이때 노드 y도 이 삭제작업 case1, 2일어날때까지 재귀적으로 수행해야한다.
# 이진 검색 트리 삭제 의사 코드 1
TREE-DELETE(T, z) if z.left == NIL or z.right == NIL #case 1, 2일때, y는 z then y <- z else y <- TREE-SUCCESOR(z) # case 3일때, y = z의 직후원소
if y.left != NIL then x <- y.left else x <- y.right
if x != NIL then x.p <- p.y
if y.p = NIL then T.root <- x else if y = y.p.left then y.p.left <- x else y.p.right <- x
if y != z then x.key <- y.key y의 부가 data를 z에 복사 return y |
# 이진 트리의 삭제 의사 코드 2(둘중에 하나만..)
TRANSPLANT(T, u, v) # 트리 T와 두개의 노드 u, v 위치교환 함수 if u.p == NIL # u가 T의 루트일때 T.root = v elseif u == u.p.left # u가 T의 왼쪽 자식 노드일때, 해당 노드 v로 갱신 u.p.left = v else u.p.right == v # u가 T의 오른 오른 자식 노드일때, 해당 노드 v로 갱신 if v != NIL # v가 NIL아니면 v.p 갱신 v.p = u.p
TREE-DELETE(T, z) if z.left == NIL # 노드 z가 왼쪽 자식 노드 없을때 TRANSPLANT(T, z, z.right) elseif z.right == NIL # 노드 z가 오른쪽 자식 노드 없을때 TRANSPLANT(T, z, z.left) else y == TREE_MINIMUM(z.right) # 노드 z가 두자식 노드를 가지는 경우(z의 직후원소 y 찾음) if y.p != z TRANSPLANT(T, y, y.right) # y의 오른자식 노드가 y의 부모의 자식노드가 되게 바꾸고 y.right = z.right # z의 오른자식노드를 y의 오른자식 노드로 삼는다. y.right.p = y TRANSPLANT(T, z, y) # 노드 z의 부모의 자식으로 y를 교체해 넣고 y.left = z.left # y의 오른자식노드가 y의 부모 자식노드가 되게 바꾸고 y.left.p = y # y의 왼쪽 자식 노드를 z의 왼쪽 자식으로 교체한다. |
'기타 > [알고리즘 이론]' 카테고리의 다른 글
알고리즘 이론 13강. 레드블랙 트리(Red-black trees) (0) | 2019.11.29 |
---|---|
알고리즘 이론 12강(2). AVL 트리 (0) | 2019.11.22 |
알고리즘 이론 11강. 해시 테이블 (0) | 2019.11.04 |
알고리즘 이론 9강. 정렬들의 분류 (0) | 2019.10.23 |
알고리즘 이론 8강. 선형 시간(O(n))안에 정렬 (1) | 2019.10.23 |