[CLRS] [17][18] B-tree

2024. 11. 30. 01:36· CS Study/CLRS (자료구조 | 알고리즘)
목차
  1. 1. B-tree?
  2. 2. B-tree의 특징
  3. 3. Code구현

1. B-tree?

- B-tree는 Tree Data Structure의 일종으로 Binary Tree를 확장하여,

- 하나의 노드의 차수의 최댓값이 2보다 큰 Tree 라고 말 할 수 있다.

https://velog.io/@emplam27/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-%EA%B7%B8%EB%A6%BC%EC%9C%BC%EB%A1%9C-%EC%95%8C%EC%95%84%EB%B3%B4%EB%8A%94-B-Tree

 

[자료구조] 그림으로 알아보는 B-Tree

B트리는 이진트리에서 발전되어 모든 리프노드들이 같은 레벨을 가질 수 있도록 자동으로 벨런스를 맞추는 트리입니다.

velog.io

- B-tree에 대해 자료를 수집하는 중, 가장 정리가 잘된 블로그를 공유한다. 

- B-tree의 개념은 해당 링크를 타서 학습하고, 코드 구현은 나의 블로그를 참고하기 바란다.

2. B-tree의 특징

'''

최대M개의 자식을 가질 수 있는 B-tree를 M차 B-tree라고 한다.

1. 노드는 최대 M개부터 M / 2개 까지의 자식을 가질 수 있다.(정렬되어 있는 상태다)

2. 노드에는 최대 M-1개부터 [M/2]-1 개의 키가 포함가능하다.

3. 노드의 키가 x개라면 자식의 수는 x + 1개이다.

4. 최소차수가 t라면 M = 2t-1을 만조한다. 

'''

 

3. Code구현

class BTreeNode:
    def __init__(self, t, is_leaf=True):
        self.t = t  # 최소 차수 (degree)
        self.keys = []  # 키들을 저장
        self.children = []  # 자식 노드를 저장
        self.is_leaf = is_leaf  # Leaf 노드 여부

    def traverse(self):
        """노드의 키들을 출력"""
        i = 0
        for i in range(len(self.keys)):
            if not self.is_leaf:
                self.children[i].traverse()
            print(self.keys[i], end=" ")
        if not self.is_leaf:
            self.children[i + 1].traverse()

    def search(self, k):
        """키 k를 검색"""
        i = 0
        while i < len(self.keys) and k > self.keys[i]:
            i += 1
        if i < len(self.keys) and self.keys[i] == k:
            return self
        if self.is_leaf:
            return None
        return self.children[i].search(k)

class BTree:
    def __init__(self, t):
        self.root = BTreeNode(t)
        self.t = t

    def traverse(self):
        """B-트리를 출력"""
        if self.root is not None:
            self.root.traverse()

    def search(self, k):
        """키 k를 검색"""
        if self.root is None:
            return None
        else:
            return self.root.search(k)

    def insert(self, k):
        """키 k를 삽입"""
        root = self.root
        if len(root.keys) == 2 * self.t - 1:
            # 루트가 가득 찼을 경우 분리
            s = BTreeNode(self.t, is_leaf=False)
            self.root = s
            s.children.append(root)
            self._split_child(s, 0)
            self._insert_non_full(s, k)
        else:
            self._insert_non_full(root, k)

    def _insert_non_full(self, x, k):
        """노드가 가득 차지 않았을 때 삽입"""
        i = len(x.keys) - 1
        if x.is_leaf:
            # Leaf 노드에 삽입
            x.keys.append(None)
            while i >= 0 and k < x.keys[i]:
                x.keys[i + 1] = x.keys[i]
                i -= 1
            x.keys[i + 1] = k
        else:
            # 자식으로 내려가기
            while i >= 0 and k < x.keys[i]:
                i -= 1
            i += 1
            if len(x.children[i].keys) == 2 * self.t - 1:
                self._split_child(x, i)
                if k > x.keys[i]:
                    i += 1
            self._insert_non_full(x.children[i], k)

    def _split_child(self, x, i):
        """자식 노드를 분리"""
        t = self.t
        y = x.children[i]
        z = BTreeNode(t, is_leaf=y.is_leaf)
        x.keys.insert(i, y.keys[t - 1])
        x.children.insert(i + 1, z)

        # z로 키와 자식들을 옮기기
        z.keys = y.keys[t:]
        y.keys = y.keys[:t - 1]
        if not y.is_leaf:
            z.children = y.children[t:]
            y.children = y.children[:t]

    def delete(self, k):
        """키 k를 삭제"""
        if not self.root:
            print("트리가 비어있습니다.")
            return
        self._delete(self.root, k)
        if len(self.root.keys) == 0:
            if self.root.is_leaf:
                self.root = None
            else:
                self.root = self.root.children[0]

    def _delete(self, node, k):
        t = self.t
        i = 0
        while i < len(node.keys) and k > node.keys[i]:
            i += 1

        # 1. 키가 노드에 존재하는 경우
        if i < len(node.keys) and node.keys[i] == k:
            if node.is_leaf:
                node.keys.pop(i)  # Leaf에서 바로 삭제
            else:
                self._delete_internal_node(node, k, i)
        elif not node.is_leaf:
            self._delete_non_leaf(node, k, i)
        else:
            print(f"키 {k}가 트리에서 존재하지 않습니다.")

    def _delete_internal_node(self, node, k, i):
        t = self.t
        if len(node.children[i].keys) >= t:
            # 전임자 키 사용
            pred = self._get_predecessor(node, i)
            node.keys[i] = pred
            self._delete(node.children[i], pred)
        elif len(node.children[i + 1].keys) >= t:
            # 후임자 키 사용
            succ = self._get_successor(node, i)
            node.keys[i] = succ
            self._delete(node.children[i + 1], succ)
        else:
            # 병합 후 삭제
            self._merge(node, i)
            self._delete(node.children[i], k)

    def _delete_non_leaf(self, node, k, i):
        t = self.t
        child = node.children[i]
        if len(child.keys) >= t:
            self._delete(child, k)
        elif i != len(node.keys) and len(node.children[i + 1].keys) >= t:
            self._borrow_from_next(node, i)
            self._delete(child, k)
        elif i != 0 and len(node.children[i - 1].keys) >= t:
            self._borrow_from_prev(node, i)
            self._delete(child, k)
        else:
            if i != len(node.keys):
                self._merge(node, i)
            else:
                self._merge(node, i - 1)
            self._delete(node.children[i], k)

    def _get_predecessor(self, node, i):
        current = node.children[i]
        while not current.is_leaf:
            current = current.children[-1]
        return current.keys[-1]

    def _get_successor(self, node, i):
        current = node.children[i + 1]
        while not current.is_leaf:
            current = current.children[0]
        return current.keys[0]

    def _borrow_from_prev(self, node, i):
        child = node.children[i]
        sibling = node.children[i - 1]
        child.keys.insert(0, node.keys[i - 1])
        node.keys[i - 1] = sibling.keys.pop(-1)
        if not sibling.is_leaf:
            child.children.insert(0, sibling.children.pop(-1))

    def _borrow_from_next(self, node, i):
        child = node.children[i]
        sibling = node.children[i + 1]
        child.keys.append(node.keys[i])
        node.keys[i] = sibling.keys.pop(0)
        if not sibling.is_leaf:
            child.children.append(sibling.children.pop(0))

    def _merge(self, node, i):
        child = node.children[i]
        sibling = node.children[i + 1]
        child.keys.append(node.keys.pop(i))
        child.keys.extend(sibling.keys)
        if not child.is_leaf:
            child.children.extend(sibling.children)
        node.children.pop(i + 1)

 

'CS Study > CLRS (자료구조 | 알고리즘)' 카테고리의 다른 글

[CLRS] [20-1] Representation of graphs  (0) 2024.11.30
[CLRS] [19] disjoint set(Union-Find)  (0) 2024.11.30
[CLRS] [16] Amortized Analysis (분할 상환 분석)  (0) 2024.11.29
[CLRS] [15] Greedy Algorithm  (0) 2024.11.27
[CLRS] [14-3] Dynamic Programming - Longest Common Subsequence(LCS)  (0) 2024.11.27
  1. 1. B-tree?
  2. 2. B-tree의 특징
  3. 3. Code구현
'CS Study/CLRS (자료구조 | 알고리즘)' 카테고리의 다른 글
  • [CLRS] [20-1] Representation of graphs
  • [CLRS] [19] disjoint set(Union-Find)
  • [CLRS] [16] Amortized Analysis (분할 상환 분석)
  • [CLRS] [15] Greedy Algorithm
23학번이수현
23학번이수현
23학번이수현
밑바닥부터 시작하는 AI보안전문가
23학번이수현
전체
오늘
어제
  • 분류 전체보기 (240)
    • Statistic Study (47)
      • Mathematical Statistics(수리통.. (47)
    • Mathematics Study (15)
      • Linear Algebra (선형대수학) (15)
    • CS Study (71)
      • CLRS (자료구조 | 알고리즘) (49)
      • Database(DB) (11)
      • C++ (11)
      • 객체지향 프로그래밍(OOP) (0)
    • DS Study (56)
      • CS 229(Machine Learning) (19)
      • CS 224n(NLP) (5)
      • Web Scraping (7)
      • R4DS(R언어) (20)
      • 밑바닥부터 시작하는 딥러닝 1 (5)
    • 코딩테스트 (5)
      • 백준-Python (5)
    • Paper Review(논문 리뷰) (43)
      • Deep Learning (16)
      • TCGA 관련 논문 (4)
      • Computer Vision (18)
      • NLP (5)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • web scraping
  • cs229
  • Machine Learning
  • R4DS
  • 딥러닝
  • 알고리즘
  • AI
  • R언어
  • C++
  • cs 224n
  • introduction to algoritmhs
  • Algorithms
  • LSTM
  • clrs
  • 수리통계학
  • Linear Algebra
  • Data Structure
  • 시간복잡도
  • db
  • Introduction to Algorithms
  • deep learning
  • 자료구조
  • 선형대수학
  • 백준
  • 파이썬
  • graph
  • NLP
  • 데이터분석
  • 논문 리뷰
  • 정렬

최근 댓글

최근 글

hELLO · Designed By 정상우.v4.2.2
23학번이수현
[CLRS] [17][18] B-tree
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.