<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ko">
	<id>https://devhrxoobm.itwiki.kr/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=%ED%95%9C%EB%8F%99%ED%9B%88</id>
	<title>IT 위키 - 사용자 기여 [ko]</title>
	<link rel="self" type="application/atom+xml" href="https://devhrxoobm.itwiki.kr/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=%ED%95%9C%EB%8F%99%ED%9B%88"/>
	<link rel="alternate" type="text/html" href="https://devhrxoobm.itwiki.kr/w/%ED%8A%B9%EC%88%98:%EA%B8%B0%EC%97%AC/%ED%95%9C%EB%8F%99%ED%9B%88"/>
	<updated>2026-09-16T05:25:18Z</updated>
	<subtitle>사용자 기여</subtitle>
	<generator>MediaWiki 1.45.1</generator>
	<entry>
		<id>https://devhrxoobm.itwiki.kr/index.php?title=B%2B_%ED%8A%B8%EB%A6%AC&amp;diff=40244</id>
		<title>B+ 트리</title>
		<link rel="alternate" type="text/html" href="https://devhrxoobm.itwiki.kr/index.php?title=B%2B_%ED%8A%B8%EB%A6%AC&amp;diff=40244"/>
		<updated>2025-02-13T23:46:02Z</updated>

		<summary type="html">&lt;p&gt;한동훈: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;B+ 트리&#039;&#039;&#039;(B+ Tree)는 B 트리(B-Tree)의 확장된 버전으로, 데이터베이스 및 파일 시스템에서 효율적인 검색 및 범위 쿼리를 수행하는 데 사용된다.  B+ 트리는 모든 키를 리프 노드(Leaf Nodes)에 저장하며, 리프 노드끼리는 연결 리스트(Linked List)로 연결되어 있다.&lt;br /&gt;
==개요==&lt;br /&gt;
B+ 트리는 B 트리와 유사하지만 몇 가지 중요한 차이점이 있다.&lt;br /&gt;
*&#039;&#039;&#039;리프 노드에만 키와 데이터 저장&#039;&#039;&#039;&lt;br /&gt;
**내부 노드(Internal Nodes)는 탐색을 위한 인덱스 역할만 수행하고, 실제 데이터는 리프 노드에 저장된다.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;리프 노드 연결 리스트&#039;&#039;&#039;&lt;br /&gt;
**리프 노드끼리 연결 리스트(Linked List) 형태로 연결되어 있어 범위 검색(Range Query)이 매우 빠르다.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;균형 유지&#039;&#039;&#039;&lt;br /&gt;
**모든 리프 노드는 동일한 깊이를 가지며, 항상 균형을 유지한다.&lt;br /&gt;
==B+ 트리의 속성==&lt;br /&gt;
1. 내부 노드는 키만 저장하며, 실제 데이터는 리프 노드에만 저장된다.  2. 리프 노드는 이중 연결 리스트(Double Linked List) 형태로 연결되어 있다.  3. 각 노드는 최소 ⌈m/2⌉개의 자식과 최대 m개의 자식을 가질 수 있다.  4. 모든 리프 노드는 동일한 깊이에 존재한다.  5. 검색, 삽입, 삭제 연산의 시간 복잡도는 O(log n)이다.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+B+ 트리의 특징&lt;br /&gt;
!속성!!설명&lt;br /&gt;
|-&lt;br /&gt;
|키 저장 위치||리프 노드에만 저장&lt;br /&gt;
|-&lt;br /&gt;
|내부 노드&lt;br /&gt;
```mediawiki&lt;br /&gt;
||인덱스 역할만 수행&lt;br /&gt;
|-&lt;br /&gt;
|리프 노드 연결||연결 리스트로 연결되어 있음&lt;br /&gt;
|-&lt;br /&gt;
|탐색 성능||빠름 (리프 노드에서만 탐색)&lt;br /&gt;
|-&lt;br /&gt;
|범위 검색||매우 빠름 (리프 노드 간 연결 이용)&lt;br /&gt;
|}&lt;br /&gt;
==B+ 트리 vs B 트리==&lt;br /&gt;
B+ 트리와 B 트리는 유사하지만 몇 가지 중요한 차이점이 있다.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+B+ 트리와 B 트리 비교&lt;br /&gt;
!기준!!B 트리!!B+ 트리&lt;br /&gt;
|-&lt;br /&gt;
|키 저장 위치||내부 노드와 리프 노드||모든 키가 리프 노드에 저장&lt;br /&gt;
|-&lt;br /&gt;
|탐색 속도||느림 (내부 노드에서도 탐색)||빠름 (리프 노드에서만 탐색)&lt;br /&gt;
|-&lt;br /&gt;
|범위 검색||상대적으로 비효율적||빠름 (리프 노드 연결 리스트 사용)&lt;br /&gt;
|-&lt;br /&gt;
|리프 노드 연결||X||O (이중 연결 리스트)&lt;br /&gt;
|}&lt;br /&gt;
==B+ 트리 연산==&lt;br /&gt;
===1. 삽입 (Insertion)===&lt;br /&gt;
1. 적절한 리프 노드를 찾아 삽입한다.  &lt;br /&gt;
&lt;br /&gt;
2. 노드가 초과(m개의 키)되면 중앙 키를 상위 노드로 올리고, 노드를 분할한다.&lt;br /&gt;
===2. 삭제 (Deletion)===&lt;br /&gt;
1. 삭제 후 노드에 남아 있는 키 개수를 확인한다.  &lt;br /&gt;
&lt;br /&gt;
2. 최소 키 개수보다 적으면 형제 노드에서 빌리거나, 병합을 수행한다.&lt;br /&gt;
===3. 검색 (Search)===&lt;br /&gt;
1. 루트에서 시작하여 적절한 자식 노드를 따라가며 키를 찾는다.  &lt;br /&gt;
&lt;br /&gt;
2. O(log n)의 시간 복잡도로 검색 가능하다.&lt;br /&gt;
==B+ 트리 구현 (Python)==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class BPlusTreeNode:&lt;br /&gt;
    def __init__(self, leaf=False):&lt;br /&gt;
        self.leaf = leaf&lt;br /&gt;
        self.keys = []&lt;br /&gt;
        self.children = []&lt;br /&gt;
        self.next = None  # 리프 노드 연결 리스트&lt;br /&gt;
&lt;br /&gt;
class BPlusTree:&lt;br /&gt;
    def __init__(self, t):&lt;br /&gt;
        self.root = BPlusTreeNode(True)&lt;br /&gt;
        self.t = t  # 최소 차수&lt;br /&gt;
&lt;br /&gt;
    def search(self, node, key):&lt;br /&gt;
        i = 0&lt;br /&gt;
        while i &amp;lt; len(node.keys) and key &amp;gt; node.keys[i]:&lt;br /&gt;
            i += 1&lt;br /&gt;
&lt;br /&gt;
        if node.leaf:&lt;br /&gt;
            if i &amp;lt; len(node.keys) and key == node.keys[i]:&lt;br /&gt;
                return node&lt;br /&gt;
            return None&lt;br /&gt;
&lt;br /&gt;
        return self.search(node.children[i], key)&lt;br /&gt;
&lt;br /&gt;
    def insert(self, key):&lt;br /&gt;
        root = self.root&lt;br /&gt;
        if len(root.keys) == (2 * self.t) - 1:&lt;br /&gt;
            new_root = BPlusTreeNode(False)&lt;br /&gt;
            new_root.children.append(self.root)&lt;br /&gt;
            self.split_child(new_root, 0)&lt;br /&gt;
            self.root = new_root&lt;br /&gt;
            self.insert_non_full(new_root, key)&lt;br /&gt;
        else:&lt;br /&gt;
            self.insert_non_full(root, key)&lt;br /&gt;
&lt;br /&gt;
    def insert_non_full(self, node, key):&lt;br /&gt;
        i = len(node.keys) - 1&lt;br /&gt;
        if node.leaf:&lt;br /&gt;
            node.keys.append(None)&lt;br /&gt;
            while i &amp;gt;= 0 and key &amp;lt; node.keys[i]:&lt;br /&gt;
                node.keys[i + 1] = node.keys[i]&lt;br /&gt;
                i -= 1&lt;br /&gt;
            node.keys[i + 1] = key&lt;br /&gt;
        else:&lt;br /&gt;
            while i &amp;gt;= 0 and key &amp;lt; node.keys[i]:&lt;br /&gt;
                i -= 1&lt;br /&gt;
            i += 1&lt;br /&gt;
            if len(node.children[i].keys) == (2 * self.t) - 1:&lt;br /&gt;
                self.split_child(node, i)&lt;br /&gt;
                if key &amp;gt; node.keys[i]:&lt;br /&gt;
                    i += 1&lt;br /&gt;
            self.insert_non_full(node.children[i], key)&lt;br /&gt;
&lt;br /&gt;
    def split_child(self, node, i):&lt;br /&gt;
        t = self.t&lt;br /&gt;
        y = node.children[i]&lt;br /&gt;
        z = BPlusTreeNode(y.leaf)&lt;br /&gt;
        node.keys.insert(i, y.keys[t - 1])&lt;br /&gt;
        node.children.insert(i + 1, z)&lt;br /&gt;
        z.keys = y.keys[t:(2 * t - 1)]&lt;br /&gt;
        y.keys = y.keys[0:(t - 1)]&lt;br /&gt;
        if not y.leaf:&lt;br /&gt;
            z.children = y.children[t:(2 * t)]&lt;br /&gt;
            y.children = y.children[0:t]&lt;br /&gt;
        if y.leaf:&lt;br /&gt;
            z.next = y.next&lt;br /&gt;
            y.next = z&lt;br /&gt;
&lt;br /&gt;
    def traverse(self, node):&lt;br /&gt;
        if node.leaf:&lt;br /&gt;
            while node:&lt;br /&gt;
                print(node.keys, end=&amp;quot; → &amp;quot;)&lt;br /&gt;
                node = node.next&lt;br /&gt;
            print(&amp;quot;None&amp;quot;)&lt;br /&gt;
        else:&lt;br /&gt;
            for i in range(len(node.keys)):&lt;br /&gt;
                self.traverse(node.children[i])&lt;br /&gt;
            self.traverse(node.children[len(node.keys)])&lt;br /&gt;
&lt;br /&gt;
# B+ 트리 테스트&lt;br /&gt;
bplustree = BPlusTree(3)  # 최소 차수 t = 3&lt;br /&gt;
for key in [10, 20, 5, 6, 12, 30, 7, 17]:&lt;br /&gt;
    bplustree.insert(key)&lt;br /&gt;
&lt;br /&gt;
print(&amp;quot;B+ 트리 리프 노드 순회 결과:&amp;quot;)&lt;br /&gt;
bplustree.traverse(bplustree.root)&lt;br /&gt;
print(&amp;quot;\n&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==같이 보기==&lt;br /&gt;
*[[B 트리]]&lt;br /&gt;
*[[이진 검색 트리]]&lt;br /&gt;
*[[AVL 트리]]&lt;br /&gt;
*[[트리 (자료 구조)]]&lt;br /&gt;
==참고 문헌==&lt;br /&gt;
*Cormen, T. H., Leiserson, C. E., Rivest, R. L., &amp;amp; Stein, C. (2009). &#039;&#039;Introduction to Algorithms&#039;&#039;. MIT Press.&lt;br /&gt;
*[https://www.geeksforgeeks.org/b-plus-tree-set-1-introduction/ GeeksforGeeks - B+ Tree Introduction]&lt;br /&gt;
[[분류:알고리즘]]&lt;br /&gt;
[[분류:트리]]&lt;/div&gt;</summary>
		<author><name>한동훈</name></author>
	</entry>
</feed>