B-tree 구현을 위한 검색, 삽입, 삭제 동작 과정
bottom-up 방식 구현
B-tree의 개념은 찾아보면 훨씬 더 잘 정리된 자료들이 많기 때문에 따로 정리하지 않고,
검색, 삽입, 삭제 과정만 정리하기로 했다.
(출처 : programiz)
M차 Btree
1. 노드는 ( ~ )개의 자식을 가질 수 있다.
2. 노드에는 ( ~ )개의 키가 포함될 수 있다.
노드의 키가 x개면, 자식은 (x+1)개
최소차수는 자식의 하한
최소차수 t라면 m = 2t - 1을 만족해야함
ex. 최소차수 2라면 3차 tree이며, key의 하한은 1
검색은 루트 노드에서부터 하향식으로 이루어진다.
검색하려는 키를 k 라고 하자.
k = the first key of the node
),k < the first key of the root node
), 왼쪽 자식에서 이 키를 재귀적으로 찾는다.k > the first key
), k를 현재 노드의 다음 키와 비교한다.k < next key
), 왼쪽 자식에서 이 키를 찾는다.요소를 삽입하기 위해선 1. 요소 삽입에 적절한 노드를 검색하고, 2. 필요한 경우, 노드를 분할해야 한다.
삽입은 상향식으로 이루어진다.
count
변수 활용)요소를 삭제하기 위해선 1. 삭제할 키가 있는 노드 검색, 2. 키 삭제, 3. 필요한 경우, 트리 균형 조정을 해야한다.
삭제 과정을 이해하기 위해선 두 가지 용어를 알아야 한다.
inorder predecessor
: 노드의 왼쪽 자손에서 가장 큰 키inorder successor
: 노드의 오른쪽 자손에서 가장 작은 키if 현재 노드에 키가 최소 키수보다 크다면:
그냥 삭제한다.
elif 왼쪽 형제 노드의 키가 최소 키수보다 크다면:
1. 왼쪽 형제를 방문하고, 왼쪽 형제 노드에서 가장 큰 키를 저장한다.(tmp)
2. 현재 키를 삭제한다.
3. 부모 노드를 현재 위치로 내리고, tmp를 부모 노드로 이동시킨다.
elif 오른쪽 형제 노드의 키가 최소 키수보다 크다면:
1. 오른쪽 형제를 방문하고, 오른쪽 형제 노드에서 가장 작은 키를 저장한다.(tmp)
2. 현재 키를 삭제한다.
3. 부모 노드를 현재 위치로 내리고, tmp를 부모 노드로 이동시킨다.
elif 부모의 키가 최소 키수보다 크다면 :
부모키를 내려서 왼쪽 형제 노드랑 병합한다.
(부모키란 현재 `index-1`번째 키를 의미한다.
단, 0번 index일 땐, 0번째 부모키로 처리한다.)
else (부모 노드의 키가 최소만큼이라면):
키를 삭제하고, 부모 노드를 아래로 내리고, case3의 2번 과정으로 이동한다.
if 자식이 리프인 경우:
if 그 자식의 키가 최소 키수보다 크다면:
키를 삭제한 후, 그 자식에서 가장 큰 값으로 삭제된 부분을 대체한다.
elif 내 키수가 최소 키수보다 크다면:
현재 키를 삭제한 후, 내 키의 자식 노드들을 병합한다. (왼쪽으로)
else (나와 자식 모두 최소 키수인 경우):
case 3으로 이동한다.
else (자식이 리프가 아닌 경우):
왼쪽 자손의 inorder predecessor(리프)와 현재 키의 자리를 바꾼다.
현재 키를 삭제한 후, case 1으로 이동한다.
이 경우에는 삭제할 키가 있는 노드도 최소, 내 자식들도 최소이므로, 키를 삭제하면 트리의 높이가 줄어든다.
1. 양쪽 자식을 병합하여, tmp변수에 저장한다.
2. 현재 키를 삭제한다.
3. 나의 부모 키를 왼쪽 형제 노드에 붙인다.
4. 이 형제 노드의 마지막에 tmp를 붙인다.
if 형제 노드가 최대 키수를 넘어갔다면:
삽입 연산의 4-a를 수행한 후, 종료한다.
else:
if 부모 노드가 최소 키수보다 작다면:
부모 노드에 대하여 2번 과정부터 반복한다.
else: 종료한다.