B树

Posted ZDF0414

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了B树相关的知识,希望对你有一定的参考价值。

定义:一棵M(M>2)阶的平衡搜索树
性质:以下出现的 M/2 均表示向上取整
     (1)根节点至少有两个孩子
     (2)每个非根节点有[M/2,M]个孩子
     (3)每个非根节点有[M/2,M-1]个关键字,并且以升序排列
     (4)key[i]和key[i+1]之间的孩子节点的值介于key[i]、key[i+1]之间

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



下面来实现一下B树的插入、查找、中序的操作

#pragma once
#include<iostream>
using namespace std;
template<class K, int M=3>//M:M路的B树
struct BTreeNode

	int _size;             //标识有多少key
	K _keys[M];             //一个结点最多有M-1个key值
	BTreeNode<K,M>* _parent;
	BTreeNode<K,M>* _subs[M + 1];//一个结点最多有M个子结点
	BTreeNode<K, M>()
		: _size(0)
		, _parent(0)
	
		for (int i = 0; i < M; i++)
		
			_keys[i] = 0;
			_subs[i] = NULL;
		
		_subs[M] = NULL;
	
;
template<class K,int M=3>
class BTree

	typedef BTreeNode<K, M> Node;
public:
	BTree()
		:_root(NULL)
	
	//在B树中的查找功能
	pair<Node*, int> Find(const K& key)
	
		if (_root == NULL)
			return pair<Node*, int>(NULL, -1);;
		Node*parent = NULL;
		Node*cur = _root;
		while (cur)
		
			int i = 0;
			for (; i < cur->_size; i++)//需要查询每个结点的所有key值
			
				if (cur->_keys[i] == key)
					return pair<Node*, int>(cur, i);
				else if (cur->_keys[i]>key)//确定往子树的查找方向
					break;
			
			parent = cur;
			cur = cur->_subs[i];
		
		return pair<Node*, int>(parent, -1);
	
	bool Insert(const K& key)
	
		//1、如果根结点为空
		if (_root == NULL)
		
			_root = new Node;
			_root->_keys[0] = key;
			_root->_size++;
			return true;
		
		pair<Node*, int> _pair = Find(key);
		if (_pair.second >0 )//key已存在
			return false;
		Node* cur = _pair.first;
		Node* parent = NULL;
		Node* sub = NULL;
		K NewKey = key;
		while (1)
		
			_InsertKey(cur, NewKey, sub);
			if (cur->_size < M)//key满足要求
				return true;
			
			//说明cur->_size已经超过了B-树的要求的key值个数,则就需要向上调整
			int div = (cur->_size) / 2;//往上提的key值的下标(提的是中间结点)

			Node*tmp = new Node;//把div右边的key值都拷到tmp里,作为所提结点的右孩子
			int index = 0;
			for (int i = div + 1; i < cur->_size; i++)
			
				tmp->_keys[index] = cur->_keys[i];
				cur->_keys[i] = 0;//清0操作
				tmp->_size++;
				index++;
			
			
			//再把div以右的孩子结点拷到tmp中
			index = 0;
			for (int i = div + 1; i < cur->_size+1; i++)
			
				tmp->_subs[index] = cur->_subs[i];
				cur->_subs[i] = NULL;
				index++;
			
			
			//更新cur结点,还剩下div以左的部分
			cur->_size -= (tmp->_size + 1);
			if (cur == _root)//如果cur为根节点,则div被提上去就是新的根结点
			
				_root = new Node;
				_root->_keys[0] = cur->_keys[div];
				cur->_keys[div] = 0;//清0操作
				_root->_subs[0] = cur;
				_root->_subs[1] = tmp;
				cur->_parent = _root;
				tmp->_parent = _root;
				_root->_size++;
				return true;
			
			NewKey = cur->_keys[div];
			cur->_keys[div] = 0;//清0操作
			cur = cur->_parent;
			sub = tmp;
		
	
	
	//B树的中序遍历
	void InOrder()
	
		_InOrder(_root);
		cout << endl;
	
protected:

	//把待插入的值插入到cur的_keys的适当位置,其过程就是一个插入排序的思想
	void _InsertKey(Node*cur, K& key, Node*sub)
	
		int end = cur->_size - 1;//cur->_keys的最后一个有效key的位置
		while (end >= 0)
		
			if (cur->_keys[end] > key)
			//移动keyz值的同时,也需要对比其大的孩子结点进行移动
				cur->_keys[end + 1] = cur->_keys[end];
				cur->_subs[end + 2] = cur->_subs[end + 1];
				end--;
			
			else
				break;
		
		//找准了插入位置
		cur->_keys[end + 1] = key;
		cur->_subs[end + 2] = sub;
		if (sub)
			sub->_parent = cur;
		cur->_size++;
	
	void _InOrder(Node* root)
	
		if (root == NULL)
			return;
		int i = 0;
		for (; i < root->_size; i++)
		
			_InOrder(root->_subs[i]);
			cout << root->_keys[i]<<" ";
		
		_InOrder(root->_subs[i]);
	
private:
	Node*_root;
;


以上是关于B树的主要内容,如果未能解决你的问题,请参考以下文章

2021-10-07:将有序数组转换为二叉搜索树。给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵 高度平衡 二叉搜索树。高度平衡 二叉树是一棵满足「每个节点的左右两个子树

二叉排序树

平衡二叉搜索树(最小高度树)

平衡二叉搜索树(最小高度树)

树面试题 04.02. 最小高度树

二叉树,B树,B+树,红黑树 简介