Data structure B-Tree/b+ Tree

Source: Internet
Author: User
Tags bool constructor split

The purpose of this blog post is to introduce a tree---B-tree, and a B-tree for the extension of the C + tree, and to compare the advantages and disadvantages of B-tree and + + tree, and to illustrate the application of B-tree plus-tree. And the code that implements the B-tree


B-Tree the concept and nature of B-Tree

B-Tree is a kind of tree suitable for outside query, it is a kind of multi-fork balance Tree

In addition, it satisfies the following properties:

(1) Root node has at least two children

(2) Number of children not in the root node between "M/2, M"

(3) The number of key values for each node is between "(M/2)-1,m-1", and the keywords are sorted in ascending order

(4) All leaf nodes are on the same floor

(5) key[i],key[i+1], between the two key values of the child's value between Key[i] to key[i+1]

a m=3 B-tree.


definition of a B-tree node

Define a node for a B-tree
template<typename k,typename v,size_t M = 3>
struct btreenode
{
	pair<k,v> _kv[m ];
	
	Btreenode<k, v> *_subs[m+1];
	Btreenode<k, v> *_parent;

	Indicates the number of key values stored
	size_t _size;

	The constructor of the node
	Btreenode ()
		: _size (0)
		, _parent (NULL) {for
		(size_t i = 0; I <= M; ++i)
		{
			_subs[i] = NULL;}}
;
We define the node class as above, according to the concept of B-tree and its properties

B-Tree How to find a key value

	The lookup function, whose return value is designed to implement insert multiplexing
	pair<node*,int> find (const k& key)
	{
		//If the query is not available, The parent record of the node that needs to be inserted
		//implements the Insert multiplexing
		node* cur = _root;
		node* parent = NULL;

		while (cur)
		{
			size_t index = 0;
			while (Index < cur->_size)
			{
				if (Key > Cur->_kv[index].first)
				{
					index++;
				}
				else if (key = = Cur->_kv[index].first)
				{
					//query to, return the node of the query return
					make_pair (cur, index);
				}
				Else
				{break
					;
				}
			}
			parent = cur;
			cur = cur->_subs[index];
		}

		There is no query to return the Father node that needs to insert the node
		//implements the reuse of the Insert function
		return Make_pair (parent,-1);
	}
This is the same way as the search tree, but only because of the difference in definition, the concept is the same.

Here, Pair,pair is a struct type, the return value is the pointer to the node and the insertion method of the bool B-Tree to find the success or not

The following conditions may be encountered when inserting: (1) B-Tree is empty

When a new node is created and the root assignment (2) is inserted, the B-tree already exists with the key value

Based on the second parameter of the Find return value pair struct, you can determine if the original B-tree has a corresponding key value

If present, the insertion fails;

Otherwise insert (3) after inserting a node, the node is not full

Insert complete, direct return True (4) after inserting a node, the key value of the node is full, need to split

Splitting method:

Move the right half of the node to a new node (also move the child over when moving)

After generating the node, it is also important to note that there were no father nodes;

If not, it is necessary to refer the intermediate element to the new root node, and (5) If the split node has a Father node when splitting

This situation may continue to adjust because the previous split will give a key value to the Father node

The number of key values for the Father node is +1, and it's probably full.


The situation above is that the split node is empty, and it can be ended without further adjustment.

Analysis and comments on all cases in the code

	BOOL Insert (const pair<k, v>& kv) {//Case 1. When the root node is empty, you need to assign the value to the _root if (_root = = NULL) {_root = new Nod
			E
			_root->_size = 1;
			_root->_kv[0] = kv;
		return true; 
		}//Case 2. Not empty, locate the inserted location//If the value of second is not-1, it means that it already exists, does not need to insert pair<node*, int> ret = find (Kv.first);

		if (ret.second! =-1) return false;
		To insert node* cur = ret.first;
		node* temp = cur;
		Pair<k, v> newkv = kv;

		node* sub = NULL;

			while (1) {//In CUR node insert kv and sub _insert (cur, newkv,sub);

			Case 3. If the cur is not full, the insert succeeds//otherwise needs to be split if (Cur->_size < M) return true;
			Scenario 4. Constructs a new node TMP node* TMP = new nodes;
			size_t mid = M >> 1;
			size_t i = mid+1;

			size_t j = 0;
				Move elements in the right half of the range to TMP while (I < cur->_size) {Tmp->_kv[j] = cur->_kv[i];

				Cur->_kv[i] = pair<k, v> ();
				TMP-&GT;_SUBS[J] = cur->_subs[i];

				if (cur->_subs[i]) cur->_subs[i]->_parent = tmp;
				Adjust i++;
				j + +; Tmp->_size++;
			cur->_size--;
			}//Copy away the last right child tmp->_subs[j] = cur->_subs[i];
			Cur->_subs[i] = NULL;

			if (cur->_subs[i]) cur->_subs[i]->_parent = tmp; Scenario 5. If Cur does not have a Father node, need to create//if Cur has a Father node, then the intermediate element needs to be inserted into the Father node if (cur->_parent) {//continue to adjust upward to determine if the parent will be full newkv
				= cur->_kv[mid];
				Sub = tmp;
				cur->_size--;
			Cur = cur->_parent;
				} else {//define a new root node and place the intermediate element into that node node* newroot = new node;
				Newroot->_kv[0] = cur->_kv[mid];

				Newroot->_size = 1;
				Set the new root node for the two children cur and TMP//and modify their father node newroot->_subs[0] = cur;
				Cur->_parent = Newroot;
				NEWROOT-&GT;_SUBS[1] = tmp;

				Tmp->_parent = Newroot;

				cur->_size--;
				The root node is re-assigned _root = Newroot;
			return true; }
		}
	}

B-Tree code implementation

#pragma once #include <iostream> using namespace std; /* * Author:haohaosong * DATE:2017/2/23 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * NOTE:B
	
	ename v,size_t M = 3> struct Btreenode {pair<k,v> _kv[m];
	Btreenode<k, v> *_subs[m+1];

	Btreenode<k, v> *_parent;

	Indicates the number of key values stored size_t _size;
		The constructor of the Node Btreenode (): _size (0), _parent (NULL) {for (size_t i = 0; I <= M; ++i) {_subs[i] = NULL;

}
	}
}; B-Tree definition Template<typename K, typename v,size_t M = 3> class BTree {typedef btreenode<k, v> Node; public:// Constructor BTree (): _root (NULL) {}//Lookup function, the design of its return value implements the reuse of insert pair<node*,int> Find (const k& key) {//If the query is not available, the
		The parent of the node that needs to be inserted is recorded with parent//implements the Insert multiplexing node* cur = _root;

		node* parent = NULL;
			while (cur) {size_t index = 0;
				while (Index < cur->_size) {if (Key > Cur->_kv[index].first) {index++; } else if (key = = Cur->_kv[index].First) {//query to, return the node of the query return Make_pair (cur, index);
				} else {break;
			}} parent = cur;
		Cur = cur->_subs[index];
	}//No query, returns the parent node that needs to insert the node//implements the reuse of the Insert function return Make_pair (parent,-1); } bool Insert (const pair<k, v>& kv) {//When the root node is empty, you need to assign a value of _root if (_root = = NULL) {_root = new node
			;
			_root->_size = 1;
			_root->_kv[0] = kv;
		return true; 
		}//Not empty, locate the inserted position//If the value of second is not-1, it means that it already exists, does not need to insert pair<node*, int> ret = find (Kv.first);

		if (ret.second! =-1) return false;
		To insert node* cur = ret.first;
		node* temp = cur;
		Pair<k, v> newkv = kv;

		node* sub = NULL;

			while (1) {//In CUR node insert kv and sub _insert (cur, newkv,sub);

			If the cur is not full, the insert succeeds//otherwise needs to be split if (Cur->_size < M) return true;
			Constructs a new node, TMP node* TMP = new node;
			size_t mid = M >> 1;
			size_t i = mid+1;

			size_t j = 0; Move elements in the right half of the range to TMP while (I < cur->_size) {TMP-&GT;_KV[J] = cur->_kv[i];

				Cur->_kv[i] = pair<k, v> ();
				TMP-&GT;_SUBS[J] = cur->_subs[i];

				if (cur->_subs[i]) cur->_subs[i]->_parent = tmp;
				Adjust i++;
				j + +;
				tmp->_size++;
			cur->_size--;
			}//Copy away the last right child tmp->_subs[j] = cur->_subs[i];
			Cur->_subs[i] = NULL;

			if (cur->_subs[i]) cur->_subs[i]->_parent = tmp; If Cur does not have a Father node, it needs to be created//if Cur has a Father node, then the intermediate element needs to be inserted into the Father node if (cur->_parent) {//continue to adjust upward to determine if the parent will be full newkv = CU
				r->_kv[mid];
				Sub = tmp;
				cur->_size--;
			Cur = cur->_parent;
				} else {//define a new root node and place the intermediate element into that node node* newroot = new node;
				Newroot->_kv[0] = cur->_kv[mid];

				Newroot->_size = 1;
				Set the new root node for the two children cur and TMP//and modify their father node newroot->_subs[0] = cur;
				Cur->_parent = Newroot;
				NEWROOT-&GT;_SUBS[1] = tmp;

				Tmp->_parent = Newroot;

				cur->_size--;
				The root node is re-assigned _root = Newroot; return true;
			}}}//middle order traversal void inorder () {_inorder (_root);
	cout << Endl;
		} protected:void _insert (node* cur,const pair<k,v>& newkv,node* sub) {//here to use int, cannot use size_t, will affect the judging condition of while loop
		int index = (cur->_size)-1;

			while (index >= 0) {//Find the appropriate insertion position, jump out of the IF (Newkv.first > Cur->_kv[index].first) break;
			Move the key value backwards and move the child Cur->_kv[index + 1] = cur->_kv[index];
			Cur->_subs[index + 2] = Cur->_subs[index + 1];
		index--;
		}//Insert new KV and child cur->_kv[index+1] = newkv;

		CUR-&GT;_SUBS[INDEX+2] = Sub;

		Child exists, assigns to its father if (sub) sub->_parent = cur;
	cur->_size++;

		}//middle order traversal recursive function void _inorder (node* root) {if (root = NULL) return;
		Access each key value and its left child size_t index = 0;
			while (Index < root->_size) {_inorder (Root->_subs[index]);
			cout << root->_kv[index].first<< "";
		index++;
	}//Print the last key value of right child _inorder (Root->_subs[root->_size]);
} protected:node* _root;};
	void Testbtree () {btree<int, int> t;
	int a[] = {53, 75, 139, 49, 145, 36, 101};
		for (size_t i = 0; i < sizeof (a)/sizeof (a[0]); ++i) {T.insert (Make_pair (a[i], i));
	T.inorder ();
} t.inorder ();
 }

B + Tree B-Tree features

B + Tree is a kind of deformation tree, its basic characteristics and B-tree consistent

There are only the following differences:

(1) The key value of each node corresponds to the number of child nodes

(2) Non-leaf nodes only serve as indexes, only the leaf nodes store the data internally.

(3) All leaf nodes are strung together by a linked list and are ordered to traverse all records according to the order of the key values


Comparison of B-and + + trees Advantages of B-Tree:

Each node has a key and a corresponding value compared to a B + tree, and if the accessed element is closer to the root node, the benefits of a B + tree are accessed quickly:

(1) The leaf node is strung together with a linked list, and the speed of traversal is very fast; If you use a B-tree, you need to traverse the entire tree

(2) B + Tree data are sequentially arranged, and are connected so when searching within the interval (for example, to find scores in the 70~80 between students), B + Tree is very convenient to do

If the B-tree is used, the B-tree should traverse each layer recursively, which is inefficient.

(3) High spatial locality, high cache hit rate for B-tree and + + Tree main applications:

They are used primarily in file storage systems and in database systems.

Some mainstream databases, such as mysql,oracle, have been used for B-numbers, plus + trees

Of course, after the optimization.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.