Btree(B-树)---C++

一棵M阶(M>2)的B树,是一棵平衡的M路平衡搜索树,可以是空树或者满足一下性质:

1. 根节点至少有两个孩子

2. 每个非根节点有[ ,M]个孩子

3. 每个非根节点有[ -1,M-1]个关键字,并且以升序排列

4. key[i]和key[i+1]之间的孩子节点的值介于key[i]、key[i+1]之间

5. 所有的叶子节点都在同一层

ps: 是向上取整

#pragma once

template<class K, int M = 3>
struct BTreeNode
{
	K _keys[M];					// 关键字数组
	BTreeNode<K, M>* _subs[M + 1];	// 孩子数组
	size_t _size;				// 关键字的个数

	BTreeNode<K, M>* _parent;	// 父亲

	BTreeNode()
		:_size(0)
		, _parent(NULL)
	{
		for (size_t i = 0; i < M + 1; ++i)
		{
			_subs[i] = NULL;
		}
	}
};

template<class K, class V>
struct Pair
{
	K _first;
	V _second;

	Pair(const K& k = K(), const V& v = V())
		:_first(k)
		, _second(v)
	{}
};

template<class K, int M = 3>
class BTree
{
	typedef BTreeNode<K, M> Node;
public:
	BTree()
		:_root(NULL)
	{}

	Pair<Node*, int> Find(const K& key)
	{
		Node* parent = NULL;
		Node* cur = _root;
		while (cur)
		{
			int i = 0;
			while (i < cur->_size && cur->_keys[i] < key)
			{
				++i;
			}

			if (cur->_keys[i] == key)
			{
				return Pair<Node*, int>(cur, i);
			}

			parent = cur;
			cur = cur->_subs[i];
		}

		return Pair<Node*, int>(parent, -1);
	}

	bool Insert(const K& key)
	{
		if (_root == NULL)
		{
			_root = new Node;
			_root->_keys[0] = key;
			++_root->_size;

			return true;
		}

		Pair<Node*, int> ret = Find(key);
		if (ret._second != -1)
		{
			return false;
		}

		K k = key;
		Node* cur = ret._first;
		Node* sub = NULL;

		// 在cur节点插入一个k
		while (1)
		{
			_InsertKey(cur, k, sub);
			if (cur->_size < M)
			{
				return true;
			}

			// 分裂
			int boundary = M / 2;

			Node* tmp = new Node;
			size_t index = 0;
			size_t size = cur->_size;

			// 拷贝key
			for (int i = boundary + 1; i < size; ++i)
			{
				tmp->_keys[index++] = cur->_keys[i];
				tmp->_size++;
				cur->_size--;
			}
			// 拷贝子节点
			index = 0;
			for (int i = boundary + 1; i <= size; ++i)
			{
				tmp->_subs[index] = cur->_subs[i];
				if (tmp->_subs[index])
					tmp->_subs[index]->_parent = tmp;

				++index;
			}

			k = cur->_keys[boundary];
			cur->_size--;

			// 没有父亲
			if (cur->_parent == NULL)
			{
				_root = new Node;
				_root->_keys[0] = k;
				_root->_subs[0] = cur;
				_root->_subs[1] = tmp;
				_root->_size = 1;

				tmp->_parent = _root;
				cur->_parent = _root;

				return true;
			}

			cur = cur->_parent;
			sub = tmp;
		}
	}

	void _InsertKey(Node* cur, const K& k, Node* sub)
	{
		int i = cur->_size - 1;
		while (i >= 0)
		{
			if (cur->_keys[i] > k)
			{
				cur->_keys[i + 1] = cur->_keys[i];
				cur->_subs[i + 2] = cur->_subs[i + 1];

				--i;
			}
			else
			{
				break;
			}
		}

		cur->_keys[i + 1] = k;
		cur->_subs[i + 2] = sub;
		if (sub)
		{
			sub->_parent = cur;
		}

		cur->_size++;
	}

	void InOrder()
	{
		_InOrder(_root);
		cout << endl;
	}

	void _InOrder(Node* root)
	{
		if (root == NULL)
		{
			return;
		}

		for (size_t i = 0; i < root->_size; ++i)
		{
			_InOrder(root->_subs[i]);
			cout << root->_keys[i] << " ";
		}

		_InOrder(root->_subs[root->_size]);
	}

protected:
	Node* _root;
};

void TestBTree1()
{
	BTree<int, 1024> t1;
	int a[] = { 53, 75, 139, 49, 145, 36, 101 };
	for (int i = 0; i < sizeof(a) / sizeof(a[0]); ++i)
	{
		t1.Insert(a[i]);
	}

	t1.InOrder();
}
时间: 2025-01-02 16:48:50

Btree(B-树)---C++的相关文章

B树、B-tree B+树、B*树

BST 即二叉搜索树: 1.所有非叶子结点至多拥有两个儿子(Left和Right): 2.所有结点存储一个关键字: 3.非叶子结点的左指针指向小于其关键字的子树,右指针指向大于其关键字的子树: 如: B-树(B树) 是一种多路搜索树(并不是二叉的): 1.定义任意非叶子结点最多只有M个儿子:且M>2: 2.根结点的儿子数为[2, M]: 3.除根结点以外的非叶子结点的儿子数为[M/2, M]: 4.每个结点存放至少M/2-1(取上整)和至多M-1个关键字:(至少2个关键字) 5.非叶子结点的关键

【转】B树、B-tree B+树、B*树

原文链接 http://www.linuxidc.com/Linux/2014-11/109103.htm BST 即二叉搜索树: 1.所有非叶子结点至多拥有两个儿子(Left和Right): 2.所有结点存储一个关键字: 3.非叶子结点的左指针指向小于其关键字的子树,右指针指向大于其关键字的子树: 如: B-树(B树) 是一种多路搜索树(并不是二叉的): 1.定义任意非叶子结点最多只有M个儿子:且M>2: 2.根结点的儿子数为[2, M]: 3.除根结点以外的非叶子结点的儿子数为[M/2, M

算法14---B树

算法14---B树 更详细的讲解见http://www.xuebuyuan.com/509072.html 一棵m阶的B 树 (m叉树)的特性,如下: (1)树中每个结点含有最多含有个孩子,即m满足:ceil(m/2)-1<=n<=m-1. (2)除根结点和叶子结点外,其它每个结点至少有[ceil(m / 2)]个孩子(其中ceil(x)是一个取上限的函数): (3)若根结点不是叶子结点,则至少有2个孩子(特殊情况:没有孩子的根结点,即根结点为叶子结点,整棵树只有一个根节点): 1.1.插入(

【Oracle】7.由B-Tree算法谈Oracle的索引

索引 1.B树索引(B-TREE) B树索引是我们日常工作最最常用的索引,大家平时在工作中说的"索引"默认都是B树索引: 索引其实很简单,也很容易理解,用一本书的目录来形容最为贴切了,B树索引的结构跟图书馆的目录也很像. 2.B树索引的结构: 索引的顶层为根,它包括指向索引中下一层次的条目.下一层次为分支块,它又指向位于索引中下一层索引中下一层次的块,最底层的是叶节点,它包含指向表行的索引条目.叶块是双向关联的,这边与按键值升序或降序扫描索引: 3.索引叶条目的格式 一个索引条目包含以

树(三)&mdash;&mdash;自平衡二叉树(AVL)

简介 自平衡二叉树(AVL)属于二叉平衡树的一类,此类树主要完成一个从键到值的查找过程,即字典(或映射),它维护树高度的方式与其他数据结构不同. 自平衡规则: AVL树的左.右子树都是AVL树 左.右子树的高度差不超过1 在数据结构中,最常见的数据间关系的抽象就是集合(Collection)和字典(Dictionary). 集合就是线性表(元素允许重复),而字典是一种非多键映射关系(键不允许重复). 对集合而言,一个班中的所有学生构成一个集合,可以是有序的(有序集合)也可以是无序的(无序集合),

树与二叉树的转换与遍历

树的初始化函数(双亲法和孩子结点法两种), 建树函数, 输出树函数, 树的前序遍历函数(递归和非递归两种), 树的后序遍历函数(递归和非递归两种), 树的层次遍历函数, 一般树和二叉树的转换函数. 主菜单和副菜单. 主函数. 具体代码如下: #include <stdio.h> #include <malloc.h> #include <stdlib.h> //设置常量: #define MAX_TREE_SIZE 100 //一般树的存储结构有以下几种:双亲结点,孩子

索引背后的数据结构(B-/+Tree)

索引是数据库常见的数据结构,每个后台开发人员都应该对索引背后的数据结构有所了解. 本文通过分析B-Tree及B-/+Tree数据结构及索引性能分析及磁盘存取原理尝试着回答一下问题: 为什么B-Tree适合数据库索引及红黑树的二叉平衡树不适合作为索引 B+Tree比BTree做索引的优势 为什么MongoDB采用B-Tree作为索引结构而MySQL采用B+Tree作为索引存储结构 B-Tree B 树(B-Tree)是为磁盘等辅助存取设备设计的一种平衡查找树,它实现了以 \(O(\lg n)\)

MySQL与Btree

Btree,B+tree,B*tree 前言: 由于在查找中用二分法在查找一些边缘数据时就会产生数据查找不公平,二叉树也存在类似问题:所以就有了B-tree. B+树索引是B+树在数据库中的一种实现,是最常见也是数据库中使用最为频繁的一种索引.B+树中的B代表平衡(balance),而不是二叉(binary),因为B+树是从最早的平衡二叉树演化而来的.在讲B+树之前必须先了解二叉查找树.平衡二叉树(AVLTree)和平衡多路查找树(B-Tree),B+树即由这些树逐步优化而来. Btree是一种

mysql 深入视图和索引

版权声明:欢迎交流! 目录(?)[+] 注:求职季,巩固下MySQL知识! 1.视图 视图又叫虚表.同真实的表一样,视图包含一系列带有名称的列和行数据.但是,视图并不在数据库中以存储的数据值集形式存在.行和列数据来自由定义视图的查询所引用的表,并且在引用视图时动态生成. 视图主要有以下作用: 1.安全,权限控制.一些数据表有着重要的信息.有些字段是保密的,不能让用户直接看到.这时就可以创建一个视图,在这张视图中只保留一部分字段.这样,用户就可以查询自己需要的字段,不能查看保密的字段. 2.性能,

MySQL数据库中索引原理与数据结构

MySQL中的索引分为3种: 1,主键索引:即用主键当唯一索引 2,常规索引:实现方式为B树和哈希表 3,全文索引:实现原理类似倒排索引,常用来查询字段中包含关键字 下面复习下B-TREE和hash-table 1 B-tree B树可以在O(lgn)的时间内实现许多动态集合操作,除了用在数据库索引上,也被用在磁盘查找上. B树是一种多路查找平衡多叉树,具有以下属性: 1,如果根节点不是叶节点,则其至少有两棵子树. 2.每个非根节点所包含的关键字个数 j 满足:┌m/2┐ - 1 <= j <