码迷,mamicode.com
首页 > 其他好文 > 详细

B树的查找、插入操作

时间:2016-07-22 14:49:32      阅读:117      评论:0      收藏:0      [点我收藏+]

标签:btree

B树的性质:

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

  2. 每个非根节点有[技术分享,M]个孩子

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

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

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


以下代码实现了B树的查找和插入操作,删除操作暂未实现


插入:先找到插入结点的位置,插入后判断关键字的个数是否小于M(M为阶数),小于返回,不小于进行分裂。

删除:任一关键字K的中序前趋(后继)必是K的左子树(右子树)中最右(左)下的结点中最后(最前)一个关键字。


BTree.h

#pragma once
#include <iostream>

template<class K,int M>
struct BTreeNode
{
	K _keys[M];
	BTreeNode* _subs[M+1];
	BTreeNode* _parents;
	size_t _size;
	BTreeNode()
		: _parents(NULL)
		, _size(0)
	{
		int i = 0;
		for (; i < M; ++i){
			_keys[i] = 0;
			_subs[i] = NULL;
		}
	}
};

template<class K,int M>
class BTree
{
	typedef BTreeNode<K, M> Node, *Node_P;
public:
	BTree()
		:_root(NULL)
	{}
	~BTree()
	{}
public:
	std::pair<Node_P, int> Find(const K& key)
	{
		if (_root == NULL)
			return std::pair<Node_P, int >(NULL,-1);
		Node_P cur = _root;
		Node_P parent = NULL;
		while (cur){
			size_t i = 0;
			while (i < cur->_size){
				if (key == cur->_keys[i]){
					return std::pair<Node_P, int >(cur, i);
				}
				else if (key > cur->_keys[i]){
					i++;
				}
				else
					break;
			}
			parent = cur;
			cur = cur->_subs[i];
		}
		return std::pair<Node_P, int >(parent, -1);
	}

	bool Insert(const K& key)
	{
		if (_root == NULL){
			_root = new Node;
			_root->_keys[0] = key;
			_root->_size++;
			return true;
		}
		std::pair<Node_P, int > res = Find(key);
		if (res.second != -1)
			return false;

		K newkey = key;
		Node_P cur = res.first;
		Node_P sub = NULL;

		while (1){
			int res_index = _Insert(cur, newkey);
			cur->_subs[res_index + 1] = sub;
			//满足规则,关键字个数小于M
			if (cur->_size < M)
				return true;
			//不满足,进行分裂
			Node_P tmp = new Node;
			sub = tmp;

			size_t div = (cur->_size - 1) / 2;    //中位数
			//size_t div = MidNum(cur);//快排的方法求中位数
			size_t i = div + 1;
			size_t index = 0;
			while (i < cur->_size){
				tmp->_keys[index] = cur->_keys[i];
				tmp->_subs[index] = cur->_subs[i];
				cur->_keys[i] = K();
				cur->_subs[i] = NULL;
				tmp->_size++;
				cur->_size--;
				index++;
				i++;
			}
			tmp->_subs[index] = cur->_subs[i];
			cur->_subs[i] = NULL;

			newkey = cur->_keys[div];
			cur->_keys[div] = K ();
			cur->_size--;
			
			cur = cur->_parents;

			if (cur == NULL){
				cur = new Node;
				cur->_keys[0] = newkey;
				cur->_size++;
				cur->_subs[1] = sub;
				sub->_parents = cur;
				cur->_subs[0] = _root;
				_root->_parents = cur;
				_root = cur;
				break;
			}
			else{
				sub->_parents = cur;
			}
		}
	}

	//任一关键字K的中序前趋(后继)必是K的左子树(右子树)中最右(左)下的结点中最后(最前)一个关键字。
	//bool Remove(K& key);
	
	void InOrder()
	{
		_InOrder(_root);
		std::cout << std::endl;
	}
private:
	int _Insert(Node_P& cur, K &key)
	{
		int end = cur->_size - 1;
		while (end >= 0){
			if (cur->_keys[end] > key){
				cur->_keys[end + 1] = cur->_keys[end];
				cur->_subs[end + 2] = cur->_subs[end+1];//孩子节点跟着移动
				end--;
			}
			else
				break;
		}
		cur->_keys[end + 1] = key;
		cur->_size++;
		return end + 1;
	}

	void _InOrder(Node_P root)
	{
		if (root == NULL)
			return;
		int i = 0;
		for (; i < root->_size; ++i){
			_InOrder(root->_subs[i]);
			std::cout << root->_keys[i]<<"   ";
		}
		_InOrder(root->_subs[i]);
	}
private:
	Node_P _root;
};


void Test1()
{
	BTree<int,3> b;
	int a[7]={53, 75, 139, 49, 145, 36, 101};

	for (int i = 0; i < sizeof(a) / sizeof(a[0]); ++i)
	{
		b.Insert(a[i]);
	}
	b.InOrder();

}

BTree.cpp

#include "BTree.h"

int main()
{
	Test1();

	return 0;
}




《完》

本文出自 “零蛋蛋” 博客,谢绝转载!

B树的查找、插入操作

标签:btree

原文地址:http://lingdandan.blog.51cto.com/10697032/1828742

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!