6. 인덱스 구조 (2-1)
DESCRIPTION
6. 인덱스 구조 (2-1). 이원 탐색 트리 /AVL 트리 /m- 원 탐색 트리 / B- 트리 /B*- 트리 / 트라이. 인덱스 (index). 특징 화일의 레코드들에 대한 효율적 접근을 위한 조직 < 키 값 , 레코드 주소 ( 포인터 )> 쌍으로 구성 종류 키 값의 유형에 따른 인덱스 기본 인덱스 (primary index) : 키 값이 기본 키인 인덱스 보조 인덱스 (secondary index) : 기본 인덱스 이외의 인덱스 화일 조직에 따른 인덱스 - PowerPoint PPT PresentationTRANSCRIPT
6. 인덱스 구조 (2-1)
이원 탐색 트리 /AVL 트리 /m- 원 탐색 트리 /B- 트리 /B*- 트리 / 트라이
컴퓨터 ·IT 공학부 2
인덱스 (index)
특징 화일의 레코드들에 대한 효율적 접근을 위한 조직 < 키 값 , 레코드 주소 ( 포인터 )> 쌍으로 구성
종류 키 값의 유형에 따른 인덱스
• 기본 인덱스 (primary index) : 키 값이 기본 키인 인덱스• 보조 인덱스 (secondary index) : 기본 인덱스 이외의 인덱스
화일 조직에 따른 인덱스• 집중 인덱스 (clustered index) : 레코드들의 물리적 순서와 인덱스
엔트리 순서가 동일한 인덱스• 비집중 인덱스 (unclustered index) : 집중 형태가 아닌 인덱스
데이타 범위에 따른 인덱스• 밀집 인덱스 (dense index) : 데이타 레코드 하나에 하나의 인덱스 엔트리가 만들어지는 인덱스 . 역 인덱스 (inverted index)• 희소 인덱스 (sparse index) : 데이타 레코드 그룹 또는 데이타 블록에 하나의 엔트리가 만들어지는 인덱스
컴퓨터 ·IT 공학부 3
이원 탐색 트리 (binary search tree)
인덱스를 조직하는 한가지 방법 이진 트리 (binary tree)
유한한 수의 노드를 가진 트리 공백 (empty) 이거나 루트와 두 개의 분리된 이진 트리 즉 ,
왼쪽 서브트리 (left subtree) 와 오른쪽 서브트리 (right subtree) 로 구성
이원 탐색 트리 이진 트리 : left – root - right 순서로 탐색 각 노드 Ni : 레코드 키 Ki 와 레코드 포인터를 포함 공백이 아닌 이원 탐색 트리의 성질
• 모든 노드는 상이한 키 값들을 갖는다 .• 루트 노드 Ni 의 왼쪽 서브트리 (Left(Ni)) 에 있는 모든 노드의 키 값들은 루트
노드의 키 값보다 작다 .• 루트 노드 Ni 의 오른쪽 서브트리 (Right(Ni)) 에 있는 모든 노드의 키 값들은
루트 노드의 키 값보다 크다 .• 왼쪽 서브트리와 오른쪽 서브트리 역시 이원 탐색 트리이다 .
컴퓨터 ·IT 공학부 4
이원 탐색 트리
이진 트리와 이원 탐색 트리• 그림 (a): 이원 탐색 트리가 아닌 이진 트리• 그림 (b), (c): 이원 탐색 트리
28
12 32
10 14 30
15
11 70
5
30
42
37 44
(a) (b) (c)
컴퓨터 ·IT 공학부 5
▶ 이원 탐색 트리에서의 검색
루트 노드가 Ni 인 이원 탐색 트리에서 키 값이 K인
노드를 검색하는 방법
1. 트리가 공백 : 검색 실패
2. K=Ki : 노드 Ni 가 원하는 노드
3. K<Ki : Ni 의 왼쪽 서브트리를 검색 Ni ← Root(Left(Ni)) 로 하여 다시 검색
시작
4. K>Ki : Ni 의 오른쪽 서브트리를 검색 Ni ← Root(Right(Ni)) 로하여 다시 검색
시작
컴퓨터 ·IT 공학부 6
▶ 이원 탐색 트리에서의 검색
연결 리스트로 표현된 이원 탐색 트리의 검색 노드는 key, left, right 필드로 구성
searchBST(B, s_key) // B 는 이원 탐색 트리 , s_key 는 검색 키 값 p ← B;
if (p = null) then // 공백 이진 트리로 검색 실패 return null;
if (p.key = s_key) then // s_key 검색 성공 return p;
if (p.key < s_key) then // 오른쪽 서브트리 검색 return searchBST(p.right, s_key);
else return searchBST(p.left, s_key); // 왼쪽 서브트리 검색 end searchBST()
left key right
컴퓨터 ·IT 공학부 7
▶ 이원 탐색 트리에서의 삽입
루트 노드가 Ni 인 이원 탐색 트리에 키 값이 K 인 노드삽입
1. 트리가 공백 : K 를 루트 노드로 삽입2. K=Ki : 트리에 똑같은 키 값이 이미 존재 ( 삽입 거부 )
3. K<Ki : Ni 의 왼쪽 서브트리로 이동하여 계속 탐색4. K>Ki : Ni 의 오른쪽 서브트리로 이동하여 계속 탐색5. K 가 있어야 할 위치 ( 탐색이 실패로 끝나는 위치 ) 에 키
값이 K 인 노드를 삽입
삽입 예 : 키 값 13, 50 을 삽입
15
11 70
5
(a) 이원 탐색 트리
15
11 70
5 13
(b) 키값 13을 삽입
15
11 70
5 13
(c) 키값 50을 삽입
50
컴퓨터 ·IT 공학부 8
▶ 이원 탐색 트리에서의 삽입 알고리즘insertBST(B, new_key) // B 는 이원 탐색 트리 , new_key 는 삽입할 키 값 p ← B; while (p ≠ null) do { // 삽입하려는 키 값을 가진 노드가 이미 있는지 검사 if (new_key = p.key) then return; // 이미 삽입 키값이 존재하므로 실패 q ← p; // q 는 p 의 부모 노드를 지시 if (new_key < p.key) then p ← p.left; else p ← p.right; } newNode ← getNode(); // 삽입할 노드를 만듦 newNode.key ← new_key; // 새로 만든 노드의 키 값을 new_key 로 세팅 newNode.right ← null; // 아직 우측 하위 노드가 없으므로 null newNode.left ← null; // 아직 좌측 하위 노드가 없으므로 null if (B = null) then B ← newNode; // 트리가 공백인 경우 else if (new_key < q.key) then // q 는 탐색이 실패로 종료하게 된 원소 q.left ← newNode; else q.right ← newNode; return; end insertBST()
컴퓨터 ·IT 공학부 9
▶ 이원 탐색 트리에서의 삭제
노드 삭제 후 계속 이원 탐색 트리 성질 유지 삭제할 노드 자식 수에 따라 삭제 연산이 다름
1. 자식이 없는 리프 노드의 삭제• 단순히 그 노드를 삭제
2. 자식이 하나인 노드의 삭제• 삭제되는 노드 자리에 그 자식 노드를 위치
3. 자식이 둘인 노드의 삭제• 삭제되는 노드 자리에 왼쪽 서브트리에서 제일 큰 키 값이나 또는 오른쪽 서브트리에서 제일 작은 키 값으로 대체• 해당 서브트리에서 대체 노드를 삭제
삭제는 포인터 값 조정으로 구조 변경 삭제 표시 ( 논리적 삭제 ) 로 대체 가능
물리적으로 즉각 삭제하지 않는 경우• 검색 , 삽입 시 삭제된 노드의 키 값을 참고로 이용• 정상적 키 값이 아니므로 별도로 취급
컴퓨터 ·IT 공학부
▶ 이원 탐색 트리에서의 삭제
삭제 예 : 키 값 40, 20, 50 삭제50
30 55
20 40 52 60
25
50
30 55
20 52 60
25
(a) 삭제 전 (b) 삭제 후
이원 탐색 트리에서 리프 노드 (40) 의 삭제
50
30 55
20 52 60
25
50
30 55
25 52 60
(a) 삭제 전 (b) 삭제 후
이원 탐색 트리에서 자식이 하나인 노드 (20) 의 삭제
30
25 55
52 60
52
30 55
6025
(b) 왼쪽 서브트리의최대 키 값 (30) 으로 대체
(c) 오른쪽 서브트리의최소 키 값 (52) 으로 대체
30
25
55
52 60
50
(a) 삭제 전
이원 탐색 트리에서 자식이 둘인 노드 (50) 의 삭제
또는
10
컴퓨터 ·IT 공학부 11
▶ 이원 탐색 트리에서의 삭제 알고리즘
deleteBST(B, d_key) p ← node to be deleted; // 삭제할 키 d_key 를 가진 노드 parent ← parent node of p; // 삭제할 노드의 부모 노드 if (p = null) then return; // 삭제할 원소가 없음 case { p.left=null and p.right=null : // 삭제할 노드가 리프 노드인 경우 if (parent.left = p) then parent.left ← null; else parent.right ← null; p.left=null or p.right = null : // 삭제할 노드의 차수가 1 인 경우 if (p.left ≠ null) then { if (parent.left = p) then parent.left ← p.left; else parent.right ← p.left; } else { if (parent.left = p) then parent.left ← p.right; else parent.right ← p.right; } p.left ≠ null and p.right ≠ null : // 삭제할 노드의 차수가 2 인 경우 q←maxNode(p.left); // 왼쪽 서브트리에서 최대 키 값을 탐색 p.key ← q.key; deleteBST(p.left, p.key); } end deleteBST()
컴퓨터 ·IT 공학부 12
▶ 편향 이원 탐색 트리
편향 이원 탐색 트리 (skewed binary search
tree)
리프 노드의 탐색 시간이 최악
N 개 노드 이원 탐색 트리 최악의 탐색 시간 : N 번 탐색60
55
52
30
25
25
30
52
55
60
컴퓨터 ·IT 공학부 13
▶ 이원 탐색 트리의 성능
성능 이원 탐색 트리의 성능은 트리의 형태와 노드에 대한 접근 빈도에 의존 우수한 성능을 위해서는
1. 자주 접근되는 노드는 루트에 가장 가깝게 유지2. 이원 탐색 트리를 균형 트리 (balanced tree) 로 유지
– 모든 노드에 대해 양쪽 서브트리의 노드 수가 가능한 같게 만들어 트리의 최대 경로 길이를 최소화
이원 탐색 트리의 단점 삽입 , 삭제 후 효율적 접근을 위한 균형 유지 부담 작은 분기율 (branching factor : 2) 에 따른 긴
탐색 경로와 긴 검색 시간• 분기율이 2 라면 각 노드는 많아야 두 개의 서브트리를
가짐• N 개의 노드를 갖는 트리의 최소 높이 :
1log N
컴퓨터 ·IT 공학부 14
AVL 트리
1962 년 러시아 수학자 Adelson-Velskii 와 Landis 가 고안한 높이 균형 이진 트리 (height-balanced binary tree)
이진 트리의 높이 : 루트에서 가장 긴 경로를 가진 리프까지의 길이 AVL 높이 균형 이진 트리
삽입 , 삭제 , 검색 시간 : O(logN) 차수 (m, Order) 에 비례 트리 일부를 재균형으로 전체가 균형을 계속 유지 ( 차수 최소화 )
AVL 트리의 정의 왼쪽 서브트리의 높이와 오른쪽 서브트리의 높이 차이가 1 이하
• ½h(Left(Ni)) – h(Right(Ni))½ ≤ 1, Ni∈ T
서브트리 높이 차이에 대한 절대값이 1 이하 공백 서브트리의 높이 : -1
컴퓨터 ·IT 공학부 15
▶ AVL 트리
균형 인수 (balance factor, BF) 왼쪽 서브트리 높이에서 오른쪽 서브트리 높이를 뺀 수
BF = h(Left(T)) – h(Right(T))
균형 인수가• ±1 이하이면 AVL 성질 (AVL property) 만족• ±2 이상이면 AVL 성질 상실
AVL 트리의 모든 노드는 균형 인수가 ±1 이하임 .
컴퓨터 ·IT 공학부 16
▶ AVL 트리와 non-AVL 트리
8
106
4
8
4 12
161063
15 175 11
13
8
4 12
161063
9
(a) (b) (c)
AVL 트리
8
7
6
8
4 10
16962
14 185
12
5
3 9
742
6
(a) (b) (c)
non-AVL 트리
컴퓨터 ·IT 공학부 17
▶ AVL 트리에서의 검색과 삽입 (1)
검색 이원 탐색 트리의 검색 방법과 동일 시간 복잡도 : O(logN)
삽입 삽입되는 노드에서부터 루트까지의 경로에 있는 조상
노드들의 균형인수 (bf) 에 영향을 줄 수 있음 .
노드 삽입으로 인해 non-AVL 트리가 되면 ,
삽입된 노드와 가장 가까우면서 불균형이 된 조상 노드의 균형 인수가 ±1 이하로 트리 구조를 조정
컴퓨터 ·IT 공학부 18
▶ AVL 트리에서의 검색과 삽입 (2)
노드 삽입으로 균형 인수가 ± 2 로 된 노드 X 가 출현 다음 4 가지 경우 중 하나로 인해 발생 ( 노드 x 는 균형
인수가 ±2)
LL : x 의 왼쪽 자식 (L) 의 왼쪽 서브트리 (L) 에 삽입RR : x 의 오른쪽 자식 (R) 의 오른쪽 서브트리 (R) 에 삽입LR : x 의 왼쪽 자식 (L) 의 오른쪽 서브트리 (R) 에 삽입RL : x 의 오른쪽 자식 (R) 의 왼쪽 서브트리 (L) 에 삽입
12
8 16
14104
2 6
1
2
2
0 0
0
0
1
1
1
12
8 16
14104
2 6
1
1
0 0
0
1
0
0
(a) AVL 트리 (b) 원소 1 의 삽입으로 non-AVL 트리로 바뀜
원소 1 의 삽입으로 노드 8 의 AVL 성질 상실
컴퓨터 ·IT 공학부 19
▶ AVL 트리에서의 검색과 삽입 (3)
회전 (rotation)불균형이 발생할 때 트리 구조를 변경하여 균형을 잡아주는 것
1. 단순 회전 (single rotation)• 한 번의 회전만 필요한 균형 : LL, RR• 탐색 순서를 유지 하면서 부모와 자식 원소의 위치를 교환
2. 이중 회전 (double rotation)• 두 번의 회전이 필요한 균형 : LR, RL
i) LL 회전
T2T1T1
B
T3
A
A2
1 0
T2 T3
B0
LL
⇒
컴퓨터 ·IT 공학부 20
▶ AVL 트리에서의 검색과 삽입 (4)
ii) RR 회전
iii) LR(a) 회전
T2 T3
B
T1
A
A
-2
-1 0
T1 T2
B
0
⇒RR
T3
0B A
A
2
-1 0
C
0
LR(a)
⇒B
0
C0
컴퓨터 ·IT 공학부 21
▶ AVL 트리에서의 검색과 삽입 (5)
iv) LR(b) 회전
T2
C
T3
B-1
1
LR(b)
⇒T1
A2
T4 T2
A
T3
B0
T1
C0
T4
-1
v) LR(c) 회전
T3
C
T2
B-1
-1LR(c)
⇒T1
A2
T4
AB1
T1
C0
T4
0
T2 T3
컴퓨터 ·IT 공학부 22
▶ AVL 트리에서의 검색과 삽입 (6)
vi) RL(a) 회전
vii) RL(b) 회전
T3T2
B
1
⇒T4
A
-2
T1
BA
1
T1
C
0
T4
0
T2 T3
C
-1
RL(b)
B B
A
-2
-1 0
C
0
RL(a)
⇒ A0
C 0
컴퓨터 ·IT 공학부 23
▶ AVL 트리에서의 검색과 삽입 (7)
viii) RL(c) 회전
AVL 트리 회전
T2 T3
B
1RL(c)
⇒T4
A
-2
T1
BA
0
T1
C
0
T4
-1
T3T2
C
1
컴퓨터 ·IT 공학부 24
▶ AVL 트리에서의 검색과 삽입 (8)
키 리스트 (8, 9, 10, 2, 1, 5, 3, 6, 4, 7, 11, 12)를 차례대로
삽입하면서 AVL 트리를 구축하는 예8
9
-1
08
9
10
9
108-1
-2 0
0
0 0RR
9
108
1
1 0
2
0
9
108
2
2 0
2
1
1
0
9
102
1
0 0
1
080
LL
(a) 키 8 삽입 (b) 키 9 삽입 (c) 키 10 삽입
(d) 키 2 삽입 (e) 키 1 삽입
80
컴퓨터 ·IT 공학부 25
▶ 노드 삽입에 따른 균형 인수 (BF) 조정
노드 삽입으로 인한 균형 인수 (BF) 의 변화 새로 노드를 삽입할 때 BF 에 영향을 받는 노드는 오직 이 새로운 노드에서부터 루트까지의 경로상에 있는 노드들이다 .
새로운 노드가 왼쪽 서브트리로 삽입되면 그 부모 노드의 BF 를 하나 증가 (+1) 시키고 , 오른쪽 서브트리로
삽입되면 BF 를 하나 감소 (-1) 시킨다 .
BF 가 0 이 되면 BF 조정은 종료되고 아니면 다시 그의 부모 노드의 BF 를 변경한다 .
즉 자기가 부모 노드의 왼쪽 서브트리이면 BF 를 하나 증가 (+1) 시키고 , 오른쪽 서브트리이면 BF 를 하나 감소 (-1) 시키면서 루트까지 경로를 따라가면서 BF 조정 작업을 계속한다 .
컴퓨터 ·IT 공학부 26
▶ AVL 트리에서의 검색과 삽입 (9)
(f) 키 5 삽입
LR
9
102
2
-1 0
10
81
50
0
0 -1
050
100
8
92
1
-1 -1
10
51
30
100
(g) 키 3 삽입
(h) 키 6 삽입
8
92
1
-1 -1
10
50
30
100
60
8
92
2
-2 -1
10
51
3-1
100
60
40
8
93
1
0 -1
21
50
40
100
60
10
RL
(i) 키 4 삽입
1
2 9
8
컴퓨터 ·IT 공학부 27
▶ AVL 트리에서의 검색과 삽입 (10)
(k) 원소 11 삽입
8
3 9
1052
1 64
7
1 0
-1
0
00
2
-1
-1
-1LR
5
3 8
942
1 7 10
1 -1
0
00
0
1
0
06-1
(j) 원소 7 삽입
5
3 8
942
1 7 10
1 -2
-1
-1
0
-1
1
0
06-1
110
5
3 8
1042
1 7 11
1 0
0
00
0
1
0
06-1
90
RR
컴퓨터 ·IT 공학부 28
▶ AVL 트리에서의 검색과 삽입 (11)
(l) 키 12 삽입
5
3 8
1042
1 7 11
1 -1
-1
-10
-1
1
0
0
6
-1
9
0
120
컴퓨터 ·IT 공학부 29
▶ AVL 트리에서의 삽입 알고리즘 (1) /* AVL 트리 삽입 알고리즘 */insertAVL(new_key) if (root = new_key) then { // 공백 트리인 경우 y ← getTreeNode(); y.key ← newKey;
root ←y; root.bf ← 0; //bf 는 균형 인수 root.left ← null; root.right ← null; return true; } f ← null; a ← p ← root; q ← null; found ← false;
// phase 1: new_key 의 삽입 위치 (q) 조사 while (p ≠ null and found = false) do if (p.bf ≠ 0) then {a ← p; f ← q;} if (new_key < p.key) then {q ← p; p ← p.left;} // 왼쪽 서브트리로 이동 else if (new_key > p.key) then {q ← p; p ←
p.right;} // 오른쪽 서브트리로 이동 else {y ← p; found ← true;} } // while
// phase 2: new_key 를 삽입하고 균형화
컴퓨터 ·IT 공학부 30
▶ AVL 트리에서의 삽입 알고리즘 (2)// phase 2: new_key 를 삽입하고 균형화if (found = false) then { // new_key 는 트리에 없음 . // new_key 를 q 의 적절한 자식으로 삽입 y ← getTreeNode(); y.key ← newKey; y.left ← null; y.right ← null; y.bf ←
0; if (new_key < q.key) then q.left ← y; //q 의 왼쪽 자식으로
삽입 else q.right ← y; //q 의 오른쪽 자식으로 삽입
// a 에서 q 까지의 경로에 있는 노드의 균형 인수를 조정 . // a 의 정의에 따라 이 경로상에 있는 모든 노드들은 그 // 균형 인수가 0 이어야 되기 때문에 이들의 균형 인수는 // ±1 로 변경된다 . 따라서 // d=1 은 new_key 가 a 의 왼쪽 서브트리로 삽입되었다는 // 것을 의미하고 // d=-1 은 a 의 오른쪽 서브트리로 삽입되었다는 것을 // 의미한다 .
컴퓨터 ·IT 공학부 31
▶ AVL 트리에서의 삽입 알고리즘 (3) if (new_key > a.key) then {p ←a.right; b ← p; d ← -1;} else {p ←a.left; b ← p; d ← 1;} while (p ≠ y) do { if (new_key > p.key) then {p.bf← -1; p ← p.right;} // 오른쪽 서브트리의 높이가 1 증가 else {p.bf← 1; p ← p.left;} // 왼쪽 서브트리의 높이가 1 증가 } //while (p ≠ y) unbalanced ← true; // 트리가 불균형인지를 검사 if (a.bf = 0 or a.bf+d = 0) then // 트리가 아직 균형 {a.bf ← a.bf+d; unbalanced ← false; } if (unbalanced = true) then // 트리가 불균형 . 회전 유형을 결정 if (d = 1) then { // 왼쪽 불균형 if (b.bf = 1) then { // LL 회전 타입 a.left ← b.right; b.right ←a; a.bf ← 0; b.bf ← 0;} } else { // LR 회전 타입 c ←b.right; b.right ← c.left; a.left ← c.right; c.left ←b; c.right ← a; switch (c.bf) { case 1 : a.bf ← -1; b.bf ← 0; break; //LR(b) case -1 : b.bf ← 1; a.bf ← 0; break; //LR(c) case 0 : b.bf ← 0; a.bf ← 0; break; //LR(a) } c.bf ← 0; b ← c; // b 는 새로운 루트 } // else LR 회전 타입
컴퓨터 ·IT 공학부 32
▶ AVL 트리에서의 삽입 알고리즘 (4)
if (unbalanced = true) then // 트리가 불균형 . 회전 유형을 결정 if (d = 1) then { // 왼쪽 불균형 if (b.bf = 1) then { // LL 회전 타입 ************ } else { // LR 회전 타입 ************ } // else LR 회전 타입 } // 왼쪽 불균형 else { // 오른쪽 불균형 . 왼쪽 불균형의 대칭 코드 ……………..// RR 회전 타입 ……………..// RL 회전 타입 } if (f = null) then root ← b; // b 를 루트로하는 서브트리가 // 균형을 맞추고 새로운 서브트리가 됨 else if (a = f.left) then f.right ← b;} // if (unbalanced = true) return true;
} // if (found = false return false;
end insertAVL()
컴퓨터 ·IT 공학부 33
▶ AVL 트리의 높이
높이 균형 이진 트리의 높이 N 개의 노드를 가진 높이 균형 이진 트리는 완전 균형
이진 트리보다 45% 이상 높아지지 않음 log(N+1) ≤ h ≤ 1.4404log(N+2)-0.328
높이 균형 이진 트리 완전 균형 이진 트리 O (1.4 log N) 대 O (log N)
높이 균형 이진 트리의 탐색 시간이 더 길다 • 완전 균형 트리보다 전체 재균형 작업 발생횟수가 줄어듬
수 백만 개로 구성된 AVL 트리의 노드 탐색은 많은 횟수의 디스크 접근을 요구 m- 원 탐색 트리 고려
컴퓨터 ·IT 공학부 34
m- 원 탐색 트리 (m-way search tree) 이원 탐색 트리보다 높은 분기율 : m 개 서브트리
장점 : 트리의 높이가 감소 ( 특정 노드의 탐색 시간 감소 ) 단점 : 삽입 , 삭제 시 트리의 균형 유지를 위한 연산이 복잡
m- 원 탐색 트리의 성질 ① 노드 구조는
<n, P0, K1, P1, K2, P2, … , Pn-1, Kn, Pn> : n 은 노드 내부 표시 [n: 키 값 수 (1≤n<m), Pi: 서브트리에 대한 포인터 , Ki: 키 값 ]
② 한 노드에 있는 키 값들은 오름차순 : Ki < Ki+1 (1 ≤ i ≤ n-1)
③ Pi (0 ≤ i ≤ n-1) 가 지시하는 서브트리 모든 노드들의 키 값 < Ki+1
④ Pn 이 지시하는 서브트리의 모든 노드들의 키값 > Kn
⑤ Pi 가 지시하는 서브트리는 m- 원 서브트리
컴퓨터 ·IT 공학부 35
▶ 3- 원 탐색 트리의 예
25
180
a
b c d
e f g h i j
100 140
30 60 110 120 170 200
70 90 150 160 22010 20^ ^ 40 50^ ^
55
컴퓨터 ·IT 공학부 36
m- 원 탐색 트리
M- 원 탐색 트리에서 밀집인덱스 구조 서브트리만 가리키는 포인트 외에도 , 파일에 있는 모든
레코드 각각에 대한 별도 포인터를 가짐 .
노드구조 : <n, P0, <K1, A1>, P1, <K2, A2>, … , Pn-1, <Kn,
An>, Pn>
M- 원 탐색트리 키 값 Ki : (Ki, Ai) 쌍을 의미
Ai 는 키 값 Ki 를 포함하고 있는 데이타 레코드의 주소
별도 파일 구조를 고려 B- 트리 등장
학번 (Ki) 성명 주민번호 학년 지도교수 …레코드
컴퓨터 ·IT 공학부 37
▶ m- 원 탐색 트리의 검색
searchMT(key) // m- 원 탐색 트리의 검색 알고리즘 // key : 검색 키 값 // x : 노드 (<n, P0, K1, P1, K2, P2, … , Pn-1, Kn, Pn>) // root : 루트 노드 // n : 노드에 있는 키의 개수
x ← root; while( x != null ) do { i ← 1; n ← x.n; while( i <= n && key > x.Ki )
i ← i+1; if ( i <= x.n && key = x.Ki) then return Ai; // 키 값 key 를 가진 레코드의 주소를 반환 if (i > n) then x ← x.Pn
else x ← x.Pi-1
} //while return null; // key 와 일치하는 값이 트리에 없는 경우 end searchMT()
컴퓨터 ·IT 공학부 38
▶ m- 원 탐색 트리의 분석
m- 원 탐색 트리의 탐색시간 : 탐색 경로 길이 ( 높이 )
에 비례 각 레벨에서는 한 개의 노드만 탐색 분기율 (m) 을 최대로 하면 트리의 높이가 낮아짐
한 노드에 m-1 개 키 값을 저장하는 m- 원 탐색트리 높이 h : n = (mh-1) 개 키 값 저장
• ( 예 ) 4- 원 탐색 트리 : 높이가 3 이면 n=(43-1)=63 개의 키 값을 저장
n 개의 키를 가진 m- 원 탐색트리 최소 높이 h = logm(N+1)
최대 탐색 시간 : O (logm(N+1))
( 예 ) m=2 이면 , 이진 트리 탐색시간과 동일
컴퓨터 ·IT 공학부 39
B- 트리
1972 년 Bayer & McCreight 가 제안
균형 m- 원 탐색 트리 가장 많이 사용되는 인덱스 방법 효율적인 균형 알고리즘을 제공
차수 (order) 가 m 인 B-tree 의 특성 ① B- 트리는 공백이거나 높이가 1 이상인 m- 원 탐색 트리 ② 루트와 리프를 제외한 내부 노드
- 최소 m/2 에서 최대 m 개의 서브트리를 가짐- 적어도 m/2 - 1 개의 키 값 ( 노드의 반 이상이 채워짐 )
③ 루트 : 리프가 아니면 적어도 두 개의 서브트리를 가짐 ④ 모든 리프는 같은 레벨
컴퓨터 ·IT 공학부 40
▶ m 차 B- 트리 노드 구조
노드 구조< n, p0, <K1, A1>, P1, <K2, A2>, P2, … , Pn-1, <Kn,
An>, Pn>
① n : 키 값의 수 (1≤n<m)
P0, … , Pn : 서브트리에 대한 포인터
각 키 값 Ki 는 그 키 값을 가진 레코드에 대한 포인터 Ai
를 포함② 각 노드의 키 값들은 항상 오름차순
(1≤i ≤n-1 Ki < Ki+1) 유지
③ Pi 가 지시하는 서브트리의 키 값들은 모두 Ki+1 보다 작다 .
④ Pn 이 지시하는 서브트리의 키 값들은 모두 Kn 보다 크다 .
⑤ Pi(0≤i≤n) 가 지시하는 서브트리들은 모두 m- 원 서브 탐색 트리이다 .
B- 트리의 장점 삽입 , 삭제 뒤에도 트리의 균형 상태를 유지 저장장치의 효율성
• 각 노드의 반 이상은 항상 키 값으로 채워짐
컴퓨터 ·IT 공학부 41
▶ 3 차 B- 트리 구조
69
19 43 128 138
1451321006026 4016
7 15 18 20 30 36 42 50 58 62 65 70 110 120 130 136 140 150
a
b c
d e f g h i
j k l m n o p q r s t u v
^
^ ^ ^ ^ ^
컴퓨터 ·IT 공학부 42
▶ B- 트리에서의 연산
검색 : m- 원 탐색 트리의 직접 검색과 같은 과정 직접 탐색은 키 값에 따라 서브트리로 분기 노드에서 검색은 순차 검색 B- 트리 전체의 순차 검색은 트리의 중위 순회 (inorder
traversal) 로 수행 (left-root-right)삽입 : 새로운 키 값은 항상 리프 노드에 삽입
노드에 공간이 있는 경우 : 검색순서에 맞게 단순 삽입 노드에 공간이 없는 경우 : overflow 로 split 발생
• 해당 노드를 두 개의 노드로 분할 해당 노드에 새로운 키 값 삽입했다고 가정 중간 ( m/2 번째 ) 키 값을 기준으로 왼쪽 작은 키 값들은 그대로 두고
오른쪽 큰 키 값들은 새로운 노드에 저장 중간 키 값은 분할된 두 노드가 왼쪽 서브트리 , 오른쪽 서브트리가 되도록
부모 노드에 삽입 이 때 , 다시 overflow 가 발생하면 위와 같은 분할 (split) 작업을 반복
컴퓨터 ·IT 공학부 43
▶ B- 트리에서의 삽입
앞의 B- 트리에 새로운 키 값 22, 41, 59, 57, 54, 44, 75, 124, 122, 123 삽입
201
201
22
(a) 노드 l에 키 22 의 삽입 (b) 리프 노드 n에 키 42 의 삽입
42n
41n
42
60f
50o
58
· · ^
b
p
58f
50o
· ·
b
o’
60
59
·p
(c) 노드 o에 키 59 의 삽입
컴퓨터 ·IT 공학부 44
▶ B- 트리에서의 삽입
50o
50o
57
(d) 노드 o에 키 57 의 삽입
50o
50o
57
(d) 키 54 의 삽입으로 노드 o의 분할(54 는 부모 노드 f로 이동 )
57o’’
58f
· ·60 ·po o’
54f
· · ^
o o’’
60f’
· · ^
o’ p
(e) 노드 f에 키 54 의 삽입 (58 은 부모 노드 b에 삽입 )
컴퓨터 ·IT 공학부 45
▶ B- 트리에서의 삽입
(h) 노드 a 에 키 43 의 삽입
69
b· · ^
c
43
b· ·
b’
69 ·c
a a
19b
· ·43 ·fd e
19b
· · ^
d e
58b’
· · ^
f f’
(g) 노드 b에 키 58 의 삽입 (43 은 부모 노드 a에 삽입 )
나머지 키 값인 33, 75, 124, 122 를 차례로 삽입 : 문제가 발생하지 않음마지막 키 값인 123 을 삽입 : B- 트리는 한 레벨 증가됨
컴퓨터 ·IT 공학부 46
▶ 한 레벨 증가된 B- 트리
7 18 20 413630 5750 62 11070
16· ·
d
26· ·
e
40· ·
e’
54· ·
f
60· ·
f’
100· ·
g
123· ·
g’
132· ·
h
145· ·
i
19 ·· ·
b
58· ·
b’
120· ·
c
138· ·
c’
43
a
128
a’
ao
j k l m m’ n o o’’ o’ p q r r’ r’’ s t u v
33
15 22 42 65 7559
· · · ·
122 124 130 136 140 150
69· ·
컴퓨터 ·IT 공학부 47
▶ 3 차 B- 트리 생성 과정
키 값 43, 69, 138, 19 순으로 삽입하여 생성43
43 69
(a) 크기가 2 인 공백 루트 노드 (b) 키 값 43 의 삽입 ( 노드 1 개의 3 차 B- 트리 )
(c) 키 값 69 의 삽입 ( 노드 1 개의 3 차 B- 트리 )
69· ·
43 138
69· ·
19 13843
(d) 키 값 138 의 삽입 ( 노드 3 개의 3 차 B- 트리 )(e) 키 값 19 의 삽입 ( 노드 3 개의 3 차 B- 트리 )
컴퓨터 ·IT 공학부 48
▶ B- 트리에서의 삽입 알고리즘 B- 트리 삽입 알고리즘
// In-key : 삽입할 키 // Finished : 삽입 완료를 나타내는 플래그 // Found : 레코드가 발견되었음을 나타내는 플래그 // P : 노드에 대한 포인터 // Bignode : 오버플로 노드를 위한 변수 // N : 키 카운터
// 노드의 주소를 스택에 저장하면서 In-key 가 삽입될 위치를 탐색 Found = false;read root;
do { N = number of keys in current node; if (n-key == key in current node) found = true; else if (In-key < key1) P = Po; else if (In-key > keyN) P = PN; else P = Pi-1; /* for some i where keyi-1 < In-key <
keyi */ if (P != null) { push onto stack address of current node; read node pointed to by P; }} while (!Found && P is not null);
컴퓨터 ·IT 공학부 49
B- 트리if (Found) report In-key already in tree;else { // In-key 를 B- 트리에 삽입 P = null; Finished = false;
do { if (current node is not full) { put In-key in current node; // 노드 안에서 키 순서를 유지하도록 키를 정렬 Finished = true; } else { copy current node to Bignode; insert In-key and P into Bignode; In-key = center key of Bignode; current node = 1st half of Bignode; get space for new node, assign address to P; new node = 2nd half of Bignode; if (stack not empty) { pop top of stack; read node pointed to; } else { // 트리의 레벨이 하나 증가 get space for new node; new node = pointer to old root, In-key and P; Finished = true;
} }
} while (!Finished); }
컴퓨터 ·IT 공학부 50
▶ B- 트리에서의 삭제
1. 삭제할 키 값이 리프 노드에 있는 경우에는 그대로 삭제
2. 삭제될 키 값이 내부 노드에 있는 경우 이 키 값의 후행 키 값과 교환 후 리프 노드에서 삭제
• B- 트리 특성상 이 후행 키 값은 항상 리프 노드에 있음• 리프 노드에서의 삭제 연산이 더 간단
후행 키 값 대신 선행 키 값을 사용할 수 있음
3. 삭제 결과로 노드의 키 값 수가 B- 트리의 최소 키 값 수 (m/2 - 1) 보다 작게 되면 underflow 가 일어나
재분배나 합병을 수행
컴퓨터 ·IT 공학부 51
재분배 (redistribution)• 해당 노드의 오른쪽이나 왼쪽 형제 노드 중에서 최소 키
값보다 많은 수의 키 값을 가진 노드에서 키 값 하나를 차출• 부모 노드에 있는 키 값을 언더플로가 일어난 노드로
이동하고 , 이 빈 자리로 차출된 키 값을 이동트리 구조가 변경되지 않음
합병 (merge)• 재분배가 불가능한 경우 ( 두 형제 노드가 최소의 키 값만을
가짐 )에 적용
• 언더플로가 된 노드의 오른쪽 ( 또는 왼쪽 ) 형제 노드에 있는 키 값들과 이 두 노드를 분리시키는 부모 노드의 키 값을 합치고 트리 구조를 조정 . 합병으로 생긴 빈 노드는 제거트리 구조가 변경됨
• 이 합병 작업은 루트 노드까지 연쇄적으로 파급될 수 있음 이 경우에는 트리의 레벨이 하나 감소될 수도 있음
▶ B- 트리에서의 삭제
컴퓨터 ·IT 공학부 52
▶ B- 트리에서의 삭제
앞의 B- 트리에서 키 값 58, 7, 60, 20, 15 삭제
노드 o에서 키 값 58 의 삭제
50o
50o
58
노드 j에서 키 값 7 의 삭제
7
j
15
j
15
60f
62p
65
· ·
b
50o
62f
60p
65
· ·
b
50o
62f
65p
· ·
b
50o
노드 f에서 키 값 60 의 삭제
컴퓨터 ·IT 공학부 53
▶ B- 트리에서의 삭제
30m
36
26e
20l
· ·
b
n
40
42
·36m
30e
26l
· ·
b
n
40
42
·
노드 l에서 키 값 20 의 삭제 ( 재분배 )
15
j
19b
· ·43 ·30
e
· ·40 ·16· ·d
18
k
26
l
36
m
42
n
f
a
컴퓨터 ·IT 공학부 54
▶ B- 트리에서의 삭제
16
jk
19b
· ·43 ·30
e
· ·40 ··d
26
l
36
m
42
n
f
a
18
16
jk
30b
· ·43 ·40
e
· ·19· ·d
26
l
36
m
42
n
f
a
18
노드 j에서 키 값 15 의 삭제 ( 노드 합병 )
컴퓨터 ·IT 공학부 55
▶ B- 트리 삭제 알고리즘
B- 트리 삭제 알고리즘
// Finished : 삭제 완료를 나타내는 플래그 // Tempnode : 재분배를 위해 사용할 정상 노드 보다
50% 큰 노드 // Sibling : 인접 형제 노드 // D-key : B- 트리에서 삭제할 키
search tree for D-key forming stack of node addresses;
// 탐색은 삽입 알고리즘 참조 if (D-key is not in terminal node) {
search for successor key of D-key at terminal level (stacking node addresses);
copy successor over D-key; terminal node successor now becomes the
D-key;}
// 키를 삭제하고 트리를 재조정Finished = false;
컴퓨터 ·IT 공학부 56
B- 트리do { remove D-key if (current node is root or is not too small) Finished = true; else if (redistribution possible) { // Sibling > minimum 이면 재분배 // 재분배 실행 copy "best" Sibling, intermediate parent key, and current (too-small) node into Tempnode; copy keys and pointers from Tempnode to "best" Sibling, parent, and current node so Sibling and current node are roughly equal size; Finished = true; } else { // 적절한 Sibling 과 합병 choose best Sibling to concatenate with; put in the leftmost of the current node and Sibling the contents of both nodes and the intermediate key from the parent; discard rightmost of the two nodes; intermediate key in parent now becomes D-key; } } while (!Finished);if (no keys in root) { // 트리의 레벨을 하나 감소 new root is the node pointed to by the current root; discard old root;
}
컴퓨터 ·IT 공학부 57
B*- 트리
B- 트리의 문제점 B- 트리 구조 유지를 위한 추가적 연산 부담을 개선
• 삽입시 노드의 분할이나 재분배 , 삭제시 노드의 합병이나 재분배 발생 B*- 트리는 B- 트리의 성능 개선을 위해 Knuth 가 제안 (B- 트리 변
형 )
( 노드의 분할 , 합병 , 재분배 횟수를 줄임 )
B*- 트리① 공백이거나 높이가 1 이상인 m- 원 탐색 트리
② 루트는 리프가 아닌 이상 최소 2 개 , 최대 2(2m-2)/3+1 개의 서브트리를 갖는다 .
③ 루트와 리프를 제외한 ( 내부 ) 노드는 적어도 (2m-2)/3+1 개 서브트리 , 즉 최소 (2m-2)/3 개의 키 값을 갖는다 .
④ 모든 리프는 같은 레벨에 있다 .
컴퓨터 ·IT 공학부 58
B*- 트리
삽입으로 인한 노드 분할의 빈도를 축소 노드가 오버플로 되면 즉시 분할하는 대신1. 오버플로가 된 키 값과 포인터를 바로 인접한 형제
노드의 여유공간을 이용해 재분배2. 인접 형제 노드가 모두 만원이면 두 인접 형제 노드의 키
값들을 3 개의 노드로 분할• 한 노드가 만원이 되더라도 다른 인접 형제 노드가 만원이 될
때까지 분할은 지연• 각 내부 노드는 항상 2/3 이상 키 값으로 채워짐
동일 조건에 대해 B- 트리 보다 적은 노드로 구성
컴퓨터 ·IT 공학부 59
▶ 7 차 B*- 트리의 생성
10 20 30 40 50 60 70 80
(a) 8 개의 키 값 삽입으로 만원이 된 9 차 B*- 트리 루트 노드 (9 차에 대한 노드 분할을 위해서는 8 개의 키 값을 갖는 루트 노드 크기가 필요 )
50
10 20 30 40 60 70 80 90
(b) 키 값 90 의 삽입으로 루트 노드가 최초로 분할된 9 차 B*- 트리
컴퓨터 ·IT 공학부 60
▶ B*- 트리에서의 삽입
오버플로가 발생하면 인접 형제 노드에 여유 공간이 있는지 검사 , 여유공간이 있으면 오버플로 키 값을 부모 노드로 올려 보내고 부모 노드에
있던 분리 키 값을 형제 노드로 이동시키거나 ,
오버플로가 된 노드와 인접 형제 노드의 키 값에다 분리 키 값을 포함해서 이들을 균등하게 양분해서 저장하고 중간 키 값을 분리 키 값으로 부모 노드에 저장
여유공간이 없으면 만원이 된 두 인접 형제 노드의 키 값들을 부모 노드의 분리
키 값과 함께 3 개의 노드로 분할해서 각 노드의 키 값 수가 적어도 (2m-2)/3 이 되도록 재분배한다 . 이때 2
개의 키 값은 분리 키 값으로 부모 노드에 저장된다 .
컴퓨터 ·IT 공학부 61
▶ 5 차 B*- 트리에서의 삽입
재분배를 이용한 키 값 24 의 삽입 ( 노드 q)
q
· · · · ·18 20 22 26
s
· · ·35 37
r
· ·33
q
· · · · ·18 20 22 24
r
· ·26
s
· · · ·33 35 37
컴퓨터 ·IT 공학부 62
▶ 5 차 B*- 트리에서의 삽입
노드 분할을 이용한 키 값 23 의 삽입 ( 노드 q)
q
· · · · ·18 20 22 24
r
· ·26
s
· · · · ·33 35 37 39
r
· · ·22 33
· · ·18 20
q
q’
· · · ·23 24 26
s
· · · ·35 37 39
컴퓨터 ·IT 공학부 63
▶ B*- 트리에서의 삭제
B- 트리에서의 삭제와 유사하나 ,
키 값 삭제로 최소 키 값 수가 유지되지 않으면
1. 형제 노드로 부터 재분배를 받도록 시도
2. 형제 노드에 여유 키 값이 없으면 3 개의 노드를 2 개의 노드로 합병• 합병으로 인해 트리가 한 레벨 낮아질 수 있음 .
컴퓨터 ·IT 공학부 64
트라이 (Trie)
Trie: reTRIEval 의 약자 키를 구성하는 문자나 숫자의 순서를 이용해 키 값을 검색할 수
있는 자료 구조 m- 진 트리지만 m- 원 탐색 트리는 아님 : 키 값의 배열 순서가 다름
m- 진 트라이 (m-ary trie) 차수 m : 키 값을 표현하기 위해 사용하는 문자의 수 , 즉 기수
(radix)• 숫자 : m=10, 영문자 : m = 26
m- 진 트라이 : m 개의 포인터를 표현하는 1 차원 배열• 각 원소 ( 포인터 ) 는 기수의 원소에 1:1 로 대응 (p0 는 0,
p5 는 5)
10 진 트라이의 노드 구조P1P0 P1P1 P1P2 P1P3 P1P4 P1P5 P1P6 P1P7 P1P8 P1P9
0 1 2 3 4 5 6 7 8 9
컴퓨터 ·IT 공학부 65
트라이 (Trie)
트라이의 높이 = 키 필드의 길이10 진 트라이의 레벨 j 의 포인터 pi 는 j 번째 숫자가
i 인 모든 키 값을 나타내는 서브트라이를 가리킴
레벨 3 에 있는 p4 는 키 값의 3 번째 숫자가 4 인 키 값을 가진
서브트라이를 가리킴 . 해당 숫자가 없을 때는 널 포인터로 표시
키 값 : 루트 노드의 pi 에서 리프 노드의 pj 까지의 경로를
각 포인터에 대응하는 기수 원소로 표현한 것리프 노드에는 해당 키 값을 가진 레코드의 주소가 저장됨
키 검색 뿐만 아니라 키의 존재 유무를 빠르게 결정트라이에서 널 포인터만 가지고 있는 공백 노드는
생성하지 않음
컴퓨터 ·IT 공학부 66
▶ 높이가 4 인 10 진 트라이
0123456789
00 0 0 00
0123456789
**0*******
0123456789
00**0**000
0123456789
**0*0*0*0*
0123456789
*0*0*0*0*0
0123456789
0**0***0**
0123456789
**0**0**0*
0123456789
00**0****0
0123456789
*0**0**0**
0123456789
0 0000000
0123456789
000000000
0123456789
00000000
0123456789
0000 0000
0123456789
000000000
0123456789
000 00000
0123456789
00 000000
0123456789
00 00 0000
0123456789
000 0
0 : 널 포인터* : 해당 키값을 가지고 있는 데이타 레코드의 주소
r
a
b
c
레벨 1
레벨 2
레벨 3
레벨 4
P3
P4
P1
d
컴퓨터 ·IT 공학부 67
▶ m 진 트라이 연산
검색 검색은 리프에서 종료되거나 , 키 값이 없을 때 중간 노드에서 종료 검색 속도는 키 필드의 길이 ( 트라이의 높이 ) 에 비례 최대 검색 비용은 키 필드의 길이 장점 : 균일한 탐색시간 , 없는 키에 대한 빠른 검색
삽입 새로운 키 값이 삽입되어야 할 노드를 검색 리프 노드에 새 레코드의 주소나 존재 표시를 삽입 리프 노드가 없을 때 : 새 리프 노드를 생성하고 중간 노드를 첨가
• 노드의 첨가나 삭제는 있으나 분열이나 병합은 없음 삭제
노드와 원소들을 찾아서 널 값으로 변경 노드의 원소 값들이 모두 널 ( 공백 노드 ) 인 경우에는 노드 삭제