CMU 15-445 -- Embedded Database Logic - 12
**CMU15-445 -- Embedded Database Logic**
**第12 讲: 高级索引结构**
在前面的讲义中,我们已经讨论了基本的索引结构,如 B+ 树和哈希表。然而,在实际应用中,高级索引结构往往是必要的,以满足更复杂的查询需求。在本讲中,我们将介绍几种常见的高级索引结构。
###1. B-树B-树是一种自平衡的多项式查找树,每个结点最多包含 M 个孩子。每个结点除了存储关键字外,还存储一个指向子树根结点的指针。B-树的特点是:
* 每个结点最多包含 M 个孩子。
* 每个结点至少包含 ceil(M/2) 个孩子。
* 每个结点存储关键字的数量介于 [ceil(M/2), M] 之间。
B-树的查找过程如下:
1. 从根结点开始,比较要查找的关键字与根结点中的关键字。
2. 如果要查找的关键字小于根结点中的关键字,则进入左子树;否则,进入右子树。
3. 重复步骤1,直到找到要查找的关键字或达到叶结点。
B-树的插入过程如下:
1. 将新插入的关键字与根结点中的关键字进行比较。
2. 如果新插入的关键字小于根结点中的关键字,则将其插入左子树;否则,将其插入右子树。
3. 如果左子树或右子树达到最大孩子数,则分裂该子树,重新平衡 B-树。
B-树的删除过程如下:
1. 将要删除的关键字与根结点中的关键字进行比较。
2. 如果要删除的关键字小于根结点中的关键字,则进入左子树;否则,进入右子树。
3. 重复步骤1,直到找到要删除的关键字或达到叶结点。
4. 删除该关键字后,如果其父结点中关键字数量少于 ceil(M/2),则合并该父结点与其兄弟结点。
###2. B+树B+树是一种自平衡的多项式查找树,每个结点最多包含 M 个孩子。每个结点除了存储关键字外,还存储一个指向子树根结点的指针。B+树的特点是:
* 每个叶结点中存储的关键字数量相同。
* 每个非叶结点中存储的关键字数量介于 [ceil(M/2), M] 之间。
B+树的查找过程与 B-树类似,但在 B+树中,每个叶结点都存储一个指向下一个叶结点的指针,这样可以快速找到下一个关键字。
B+树的插入过程与 B-树类似,但在 B+树中,如果新插入的关键字小于根结点中的关键字,则将其插入左子树;否则,将其插入右子树。如果左子树或右子树达到最大孩子数,则分裂该子树,重新平衡 B+树。
B+树的删除过程与 B-树类似,但在 B+树中,如果要删除的关键字是叶结点中的关键字,则直接删除该关键字。如果要删除的关键字是非叶结点中的关键字,则找到其父结点,将其合并到其兄弟结点中。
###3. TrieTrie是一种多项式查找树,每个结点存储一个字符。每个结点最多包含 M 个孩子。Trie的特点是:
* 每个结点存储一个字符。
* 每个结点最多包含 M 个孩子。
Trie的查找过程如下:
1. 从根结点开始,比较要查找的关键字与根结点中的关键字。
2. 如果要查找的关键字小于根结点中的关键字,则进入左子树;否则,进入右子树。
3. 重复步骤1,直到找到要查找的关键字或达到叶结点。
Trie的插入过程如下:
1. 将新插入的关键字与根结点中的关键字进行比较。
2. 如果新插入的关键字小于根结点中的关键字,则将其插入左子树;否则,将其插入右子树。
3. 如果左子树或右子树达到最大孩子数,则分裂该子树,重新平衡 Trie。
Trie的删除过程如下:
1. 将要删除的关键字与根结点中的关键字进行比较。
2. 如果要删除的关键字小于根结点中的关键字,则进入左子树;否则,进入右子树。
3. 重复步骤1,直到找到要删除的关键字或达到叶结点。
4. 删除该关键字后,如果其父结点中孩子数少于 M,则合并该父结点与其兄弟结点。
###4. 哈希表哈希表是一种快速查找数据结构,每个元素都有一个唯一的索引。哈希表的特点是:
* 每个元素都有一个唯一的索引。
* 查找速度非常快。
哈希表的查找过程如下:
1. 将要查找的关键字通过哈希函数计算其索引。
2. 如果该索引存在,则返回该元素;否则,返回空或错误信息。
哈希表的插入过程如下:
1. 将新插入的关键字通过哈希函数计算其索引。
2. 如果该索引不存在,则将其插入到哈希表中。
哈希表的删除过程如下:
1. 将要删除的关键字通过哈希函数计算其索引。
2. 如果该索引存在,则删除该元素;否则,返回空或错误信息。
### 总结在本讲中,我们介绍了几种常见的高级索引结构,如 B-树、B+树、Trie 和哈希表。这些索引结构都有其特点和应用场景。通过理解这些索引结构,可以更好地设计和实现数据库系统。
###代码示例以下是使用 Python 实现 B-树、B+树、Trie 和哈希表的示例代码:
class Node: def __init__(self, key): self.key = key self.children = [] class BTree: def __init__(self, M): self.M = M def insert(self, key): root = self.root if not root: self.root = Node(key) return queue = [root] while queue: node = queue.pop(0) if len(node.children) < self.M: child = Node(key) node.children.append(child) break else: queue.extend(node.children) def search(self, key): root = self.root if not root: return None queue = [root] while queue: node = queue.pop(0) if key == node.key: return node elif key < node.key: for child in node.children: queue.append(child) else: for child in reversed(node.children): queue.append(child) class BPlusTree: def __init__(self, M): self.M = M def insert(self, key): root = self.root if not root: self.root = Node(key) return queue = [root] while queue: node = queue.pop(0) if len(node.children) < self.M: child = Node(key) node.children.append(child) break else: queue.extend(node.children) def search(self, key): root = self.root if not root: return None queue = [root] while queue: node = queue.pop(0) if key == node.key: return node elif key < node.key: for child in node.children: queue.append(child) else: for child in reversed(node.children): queue.append(child) class TrieNode: def __init__(self, char): self.char = char self.children = {} class Trie: def __init__(self): self.root = TrieNode('') def insert(self, key): node = self.root for char in key: if char not in node.children: node.children[char] = TrieNode(char) node = node.children[char] def search(self, key): node = self.root for char in key: if char not in node.children