目录
B树(B-tree)是一种自平衡的树数据结构,广泛应用于数据库和文件系统中,以便高效地进行顺序读取、写入以及查找操作。主要思想是保持数据在一种排序状态,且每个节点可以拥有多个子节点,使得系统在磁盘I/O上更加高效。
1. 自平衡:自动调整自身结构以保持平衡。
2. 所有叶子节点在同一层:这确保了查找操作的深度相同。
3. 节点的键数量:每个节点包含一个范围内的键值数量(通常由一个给定的最小度数t确定)。
4. 子树数量:如果一个节点包含n个键,必然包含n+1个子节点。
5. 有序性:每个节点中的键值是按非递减顺序储存的。
B树由Rudolf Bayer和Edward M. McCreight在1972年发明。设计的目的是为了解决因大规模数据存储而产生的慢速磁盘访问问题。
1. 高效的查询和读写操作:通过减少I/O操作来提高性能。
2. 平衡性:自我平衡机制保证了高效的树结构。
3. 适合大规模数据:尤其适用于外存储设备(如硬盘)的数据存取,提高了搜索、插入、删除等操作的速度。
1. 实现复杂:相比其他基础数据结构,B树的实现逻辑相对复杂。
2. 占用更多存储空间:为了保持平衡性,需要额外的内部节点和子节点指针。
3. 维护成本高:在插入和删除操作中需要较多的旋转和分裂操作。
1. 数据库索引
2. 文件系统(如NTFS)
3. 数据库管理系统(DBMS)
4. 内存缓冲区替换算法
5. 搜索引擎索引
6. 电子书阅读器(如Kindle)的索引
7. 存储系统的元数据管理
8. 版本控制系统
9. 多级缓存
10. 科学计算数据库
以下是一个简单的B树实现示例代码:
- #include
- #include
-
- // 定义B树的最小度数 (最低范围)
- #define T 3
-
- typedef struct BTreeNode
- {
- int keys[2 * T - 1]; // minimum degree
- struct BTreeNode *C[2 * T]; // child pointers
- int n; // current number of keys
- int leaf; // is true if leaf node
- } BTreeNode;
-
- //创建新B-树节点
- BTreeNode* createNode(int t, int leaf)
- {
- BTreeNode* newNode = (BTreeNode*) malloc(sizeof(BTreeNode));
- newNode->leaf = leaf;
- newNode->n = 0;
- return newNode;
- }
-
- //遍历B-树
- void traverse(BTreeNode* root)
- {
- if (root == NULL)
- return;
-
- int i;
- for (i = 0; i < root->n; i++)
- {
- if (root->leaf == 0) traverse(root->C[i]);
- printf(" %d", root->keys[i]);
- }
-
- if (root->leaf == 0)
- traverse(root->C[i]);
- }
-
- //在B-树中搜索关键字
- BTreeNode* search(BTreeNode* root, int k)
- {
- int i = 0;
- while (i < root->n && k > root->keys[i])
- i++;
-
- if (root->keys[i] == k)
- return root;
-
- if (root->leaf == 1)
- return NULL;
-
- return search(root->C[i], k);
- }
-
- //拆分完整节点的子节点
- void splitChild(BTreeNode* x, int i, BTreeNode* y)
- {
- BTreeNode* z = createNode(y->leaf, T);
- z->n = T - 1;
-
- for (int j = 0; j < T - 1; j++)
- z->keys[j] = y->keys[j + T];
-
- if (!y->leaf)
- {
- for (int j = 0; j < T; j++)
- z->C[j] = y->C[j + T];
- }
-
- y->n = T - 1;
-
- for (int j = x->n; j >= i + 1; j--)
- x->C[j + 1] = x->C[j];
- x->C[i + 1] = z;
-
- for (int j = x->n - 1; j >= i; j--)
- x->keys[j + 1] = x->keys[j];
- x->keys[i] = y->keys[T - 1];
-
- x->n = x->n + 1;
- }
-
- //在非完整节点中插入新密钥
- void insertNonFull(BTreeNode* x, int k)
- {
- int i = x->n - 1;
-
- if (x->leaf == 1)
- {
- while (i >= 0 && x->keys[i] > k)
- {
- x->keys[i + 1] = x->keys[i];
- i--;
- }
-
- x->keys[i + 1] = k;
- x->n = x->n + 1;
- }
- else
- {
- while (i >= 0 && x->keys[i] > k)
- i--;
-
- if (x->C[i + 1]->n == 2 * T - 1)
- {
- splitChild(x, i + 1, x->C[i + 1]);
- if (x->keys[i + 1] < k)
- i++;
- }
- insertNonFull(x->C[i + 1], k);
- }
- }
-
- //在B-树中插入新键值
- void insert(BTreeNode** root, int k)
- {
- if (*root == NULL)
- {
- *root = createNode(1, T);
- (*root)->keys[0] = k;
- (*root)->n = 1;
- }
- else
- {
- if ((*root)->n == 2 * T - 1)
- {
- BTreeNode* s = createNode(0, T);
- s->C[0] = *root;
- splitChild(s, 0, *root);
-
- int i = 0;
- if (s->keys[0] < k) i++;
- insertNonFull(s->C[i], k);
-
- *root = s;
- }
- else
- {
- insertNonFull(*root, k);
- }
- }
- }
-
- int main()
- {
- BTreeNode* root = NULL;
-
- int keys[] = {10, 20, 5, 6, 12, 30, 7, 17};
- int n = sizeof(keys) / sizeof(keys[0]);
-
- for (int i = 0; i < n; i++)
- {
- insert(&root, keys[i]);
- }
-
- printf("Traversal of constructed B-Tree: ");
- traverse(root);
-
- int k = 6;
- (search(root, k) != NULL) ? printf("\nPresent") : printf("\nNot Present");
-
- k = 15;
- (search(root, k) != NULL) ? printf("\nPresent") : printf("\nNot Present");
-
- return 0;
- }
B树是一种重要的平衡树数据结构,具有高效的插入、删除和查找操作。广泛应用于数据库系统和文件系统中,由于其自平衡特性,使得其在处理大规模数据时表现出色。实现B树需要深入理解其复杂的结构及操作。上述示例代码展示了B树的基本插入和查找操作,提供了一个简单的实现参考。