B-tree Principle and Implementation (C ++)

Source: Internet
Author: User
B tree definition a B tree T is a root tree with the following properties (root [T]): 1) each node X has the following domain: a) N [X], number of keywords currently stored in node X; B) N [x] keywords themselves, which are stored in non-descending order. Therefore, key1 [x] ≤ key2 [x] ≤... ≤ Keyn [x] [X]; c) leaf [x] is a Boolean value. If X is a leaf node, it is true. If X is an internal node, it is false. 2) each internal node X also contains N [x] + 1 pointer pointing to its child c1 [X], C2 [X],…, CN [x] + 1 [X]. Leaf nodes have no children, so their Ci domains are not defined. 3) each keyword keyi [x] separates the keyword ranges stored in each subtree. If Ki is the key word stored in the subtree with the root of CI [X, then K1 ≤ key1 [x] ≤ K2 ≤ key2 [x] ≤... ≤Keyn [x] [x] ≤kn [x] + 14) each leaf node has the same depth, that is, the height of the tree H. 5) each node has an upper and lower bound Number of keywords. These circles can be expressed by a fixed integer t ≥2, which is the minimum degree of B (that is, the number of child nodes that a node can point. A) each non-root node must have at least T-1 keywords, and each non-root internal node must have at least t children. If the fruit tree is not empty, the root node contains at least one keyword. B) each node can contain up to 2 T-1 keywords. Therefore, an internal node can have at most 2 t children. Let's say that a node is full, if it happens to have 2 T-1 keywords.
Basic operations on Tree B search for Tree B is similar to a search for a binary tree, but what is done at each node is not decided by a binary or "two-way" branch, the second is the multi-branch decision made based on the number of children of the node. To be more accurate, make N [x] + 1 branch decision at each inner node X.
Insert a keyword to tree B to insert a keyword to tree B, similar to inserting a keyword in the binary search tree. Search for the leaf node location where the new keyword is inserted. Because you cannot insert keywords into a full leaf node, You need to split a full node into two nodes based on its intermediate keywords, the intermediate keyword is promoted to the parent node of the node. However, such full-node splitting will spread up the tree. To solve this problem, we can adopt a policy that searches for the location of a New Keyword along the root of the tree, and splits all the full nodes along the route. Therefore, every time you split a full node, you can ensure that its parent node is not full.
The delete operation on the Tree B is similar to the insert operation, but it is a little complicated, because a keyword can be deleted from any node, not just a leaf node. We must ensure that a node will not become too large because of insertion, and that a node will not become too small because of deletion. Next, we will roughly describe the various situations for deleting keywords: 1) if the key word K is in node X and X is a leaf node, then K is deleted from X. 2) if K is in node X and X is an internal node, perform the following operations: a) if y, the subnode prior to k in node X, contains at least t keywords, then find the precursor K' In the subtree where K is rooted in Y '. Recursively Delete K' and replace K with K' in X. B) symmetric, if the subnode Z located after K in node X contains at least t keywords, find the successor K' In the subtree where K is rooted in Z '. Recursively Delete K' and replace K with K' in X. C) otherwise, if both Y and Z have only the T-1 keyword, merge all the keywords in K and Z into y, making X lose K and pointer to Z, this causes y to contain 2 T-1 keywords. Then, release Z and recursively Delete K from Y. 3) if the keyword K is not in inner node X, determine the root CI [x] of the correct subtree containing K. If Ci [x] has only T-1 keywords, perform step 3A or 3B to ensure that we are dropped to a node that contains at least t keywords. Then, it ends by recursion of a suitable subnode of X. A) if CI [x] contains only the T-1 keywords, but one of its adjacent sibling nodes contains at least t keywords, then a keyword in X is dropped to CI [X, raise a keyword in the adjacent left or right brothers of CI [x] to X, and move the appropriate child node pointer in the sibling to CI [X, this adds an additional keyword to CI [X. B) If all adjacent sibling nodes of CI [X] and CI [x] contain only the T-1 keywords, merge CI [x] with any sibling, then, a key word of X is moved to the newly merged node to become the intermediate key word of the new node.
B-tree C ++ implementation code
# Pragma oncetemplate <class T> class cbtree {PRIVATE: static const int M = 3; // the minimum level of the B tree static const int key_max = 2 * M-1; // maximum number of nodes containing keywords static const int key_min = M-1; // minimum number of non-root nodes containing keywords static const int child_max = key_max + 1; // maximum number of child nodes static const int child_min = key_min + 1; // minimum number of child nodes struct node {bool isleaf; // whether it is a leaf node int keynum; // Number of keywords contained in a node T keyValue [key_max]; // array of key values node * pchild [child_max]; // Number of child tree pointers Group node (bool B = true, int n = 0): isleaf (B), keynum (n) {}}; public: cbtree () {m_proot = NULL; // create an empty B tree }~ Cbtree () {clear ();} bool insert (const T & Key) // Insert a new node key to number B {If (contain (key )) // check whether this keyword already exists {return false;} else {If (m_proot = NULL) // check whether it is an empty tree {m_proot = new node ();} if (m_proot-> keynum = key_max) // check whether the root node is full {node * pnode = new node (); // create a new root node pnode-> isleaf = false; pnode-> pchild [0] = m_proot; splitchild (pnode, 0, m_proot); m_proot = pnode; // update the root node pointer} insertnonfull (m_proot, key); Return true ;}} bool remove (con St t & Key) // Delete the node key {If (! Search (m_proot, key) // {return false;} If (m_proot-> keynum = 1) // special case processing {If (m_proot-> isleaf) {clear (); Return true;} else {node * pchild1 = m_proot-> pchild [0]; node * pchild2 = m_proot-> pchild [1]; if (pchild1-> keynum = key_min & pchild2-> keynum = key_min) {mergechild (m_proot, 0); deletenode (m_proot); m_proot = pchild1 ;}}} recursive_remove (m_proot, key); Return true;} void display () const // print tree keyword {displayinconcavo (M_proot, key_max * 10);} bool contain (const T & Key) const // check whether the key exists in the B tree {return search (m_proot, key );} void clear () // clear B tree {recursive_clear (m_proot); m_proot = NULL;} PRIVATE: // Delete tree void recursive_clear (node * pnode) {If (pnode! = NULL) {If (! Pnode-> isleaf) {for (INT I = 0; I <= pnode-> keynum; ++ I) recursive_clear (pnode-> pchild [I]);} deletenode (pnode) ;}}// Delete the node void deletenode (node * & pnode) {If (pnode! = NULL) {Delete pnode; pnode = NULL ;}// search for the keyword bool search (node * pnode, const T & Key) const {If (pnode = NULL) // check whether the node pointer is null or whether the node is a leaf node {return false;} else {int I; for (I = 0; I <pnode-> keynum & Key> * (pnode-> keyValue + I); ++ I) // find the minimum subscript I {} if (I <pnode-> keynum & Key = pnode-> keyValue [I ]) {return true;} else {If (pnode-> isleaf) // check whether the node is a leaf node {return false ;} else {return search (pnode-> pchild [I], Key) ;}}}// split the subnode void splitchild (node * pparent, int nchildindex, node * pchild) {// split pchild into two nodes: pleftnode and pchild * prightnode = new node (); // The right node after split is prightnode-> isleaf = pchild-> isleaf; prightnode-> keynum = key_min; int I; for (I = 0; I <key_min; ++ I) // copy the value of the keyword {prightnode-> keyValue [I] = pchild-> keyValue [I + child_min];} If (! Pchild-> isleaf) // if it is not a leaf node, copy the child node pointer {for (I = 0; I <child_min; ++ I) {prightnode-> pchild [I] = pchild-> pchild [I + child_min] ;}} pchild-> keynum = key_min; // update the number of keywords in the left subtree for (I = pparent-> keynum; I> nchildindex; -- I) // move the values of all the keywords and the subtree pointer after nchildindex in the parent node to the back one {pparent-> pchild [I + 1] = pparent-> pchild [I]; pparent-> keyValue [I] = pparent-> keyValue [I-1];} + pparent-> keynum; // update the number of keywords of the parent node pparent-> pchild [nchildindex + 1] = prightno De; // store the right subtree pointer pparent-> keyValue [nchildindex] = pchild-> keyValue [key_min]; // raise the Middle Value of the node to the parent node} // Insert the keyword void insertnonfull (node * pnode, const T & Key) {int I = pnode-> keynum in a non-full node; // get the number of keywords in the node if (pnode-> isleaf) // pnode is the leaf node {While (I> 0 & Key <pnode-> keyValue [I-1]) // from the back forward, find the keyword insert position {pnode-> keyValue [I] = pnode-> keyValue [I-1]; // shift backward -- I ;} pnode-> keyValue [I] = key; // Insert the keyword value + + pnode-> keynum; // update the number of node keywords} else // pnode is Inner node {While (I> 0 & Key <pnode-> keyValue [I-1]) // from back to front, find the inserted subtree of the Keyword -- I; node * pchild = pnode-> pchild [I]; // target subtree node pointer if (pchild-> keynum = key_max) // the subtree node is full {splitchild (pnode, i, pchild); // split the subtree node if (Key> pnode-> keyValue [I]) // determine the target subtree pchild = pnode-> pchild [I + 1];} insertnonfull (pchild, key ); // Insert the keyword to the target subtree node} // print the tree void displayinconcavo (node * pnode, int count) const {If (pnode! = NULL) {int I, j; for (I = 0; I <pnode-> keynum; ++ I) {If (! Pnode-> isleaf) {displayinconcavo (pnode-> pchild [I], Count-2) ;}for (j = count; j> = 0; -- J) {cout <"-" ;}cout <pnode-> keyValue [I] <Endl ;}if (! Pnode-> isleaf) {displayinconcavo (pnode-> pchild [I], Count-2) ;}}// merge two subnodes void mergechild (node * pparent, int index) {node * pchild1 = pparent-> pchild [Index]; node * pchild2 = pparent-> pchild [index + 1]; // merge pchild2 data to pchild1pchild1-> keynum = key_max; pchild1-> keyValue [key_min] = pparent-> keyValue [Index]; // move the index value of the parent node down int I; for (I = 0; I <key_min; ++ I) {pchild1-> keyValue [I + key_min + 1] = pchild2-> keyValue [I];} If (! Pchild1-> isleaf) {for (I = 0; I <child_min; ++ I) {pchild1-> pchild [I + child_min] = pchild2-> pchild [I] ;}// the parent node deletes the index key, forward one digit after index -- pparent-> keynum; for (I = index; I <pparent-> keynum; ++ I) {pparent-> keyValue [I] = pparent-> keyValue [I + 1]; pparent-> pchild [I + 1] = pparent-> pchild [I + 2];} deletenode (pchild2); // Delete pchild2} // recursively Delete the keyword void recursive_remove (node * pnode, const T & Key) {int I = 0; while (I <pnode-> keynum & Key> P Node-> keyValue [I]) ++ I; if (I <pnode-> keynum & Key = pnode-> keyValue [I]) // keyword key {If (pnode-> isleaf) in the node pnode // pnode is a leaf node {// Delete K from pnode -- pnode-> keynum; (; I <pnode-> keynum; ++ I) {pnode-> keyValue [I] = pnode-> keyValue [I + 1] ;}return ;} else // pnode is an internal node {node * pchildprev = pnode-> pchild [I]; // The child node * pchildnext = pnode-> pchild [I + 1] of the key in the node pnode; // If (pchildprev-> keynum> = child_min) subnode of the key in the pnode // node pchildpre V contains at least the child_min keywords {T prevkey = getpredecessor (pchildprev); // obtain the key's precursor keyword recursive_remove (pchildprev, prevkey); pnode-> keyValue [I] = prevkey; // Replace the return with the key precursor keyword;} else if (pchildnext-> keynum> = child_min) // The Node pchildnext contains at least the child_min keyword {T nextkey = getsuccessor (pchildnext); // obtain the key's successor keyword recursive_remove (pchildnext, nextkey ); pnode-> keyValue [I] = nextkey; // Replace the key with the subsequent keyword return;} else // node pchildprev and pchi Ldnext contains only CHILD_MIN-1 keywords {mergechild (pnode, I); recursive_remove (pchildprev, key );}}} else // The Key keyword is not in node pnode {node * pchildnode = pnode-> pchild [I]; // If (pchildnode-> keynum = key_min) // only T-1 keywords {node * pleft = I> 0? Pnode-> pchild [I-1]: NULL; // left sibling node * pright = I <pnode-> keynum? Pnode-> pchild [I + 1]: NULL; // right sibling node Int J; If (pleft & pleft-> keynum> = child_min) // left sibling nodes have at least child_min keywords {// keywords of the I-1 in the parent node move down to pchildnode for (j = pchildnode-> keynum; j> 0; -- J) {pchildnode-> keyValue [J] = pchildnode-> keyValue [J-1];} pchildnode-> keyValue [0] = pnode-> keyValue [I-1]; If (! Pleft-> isleaf) {for (j = pchildnode-> keynum + 1; j> 0; -- J) // port the appropriate child pointer in the pleft node to pchildnode {pchildnode-> pchild [J] = pchildnode-> pchild [J-1];} pchildnode-> pchild [0] = pleft-> pchild [pleft-> keynum];} + pchildnode-> keynum; pnode-> keyValue [I] = pleft-> keyValue [pleft-> keyNum-1]; // The maximum keyword in the pleft node goes up to pnode-pleft-> keynum ;} else if (pright & pright-> keynum> = child_min) // The right sibling node has at least child_min keywords {// The I keywords in the parent node are moved down to the PC in pchildnode Hildnode-> keyValue [pchildnode-> keynum] = pnode-> keyValue [I]; ++ pchildnode-> keynum; pnode-> keyValue [I] = pright-> keyValue [0]; // The minimum keyword in the pright node is raised to pnode -- pright-> keynum; For (j = 0; j <pright-> keynum; ++ J) {pright-> keyValue [J] = pright-> keyValue [J + 1];} If (! Pright-> isleaf) {pchildnode-> pchild [pchildnode-> keynum] = pright-> pchild [0]; // The proper child pointer in the pright node is transplanted to the pchildnode for (j = 0; j <= pright-> keynum; ++ J) {pright-> pchild [J] = pright-> pchild [J + 1] ;}}// both left and right sibling nodes contain only CHILD_MIN-1 nodes else if (pleft) // merge with left sibling {mergechild (pnode, I-1); pchildnode = pleft;} else if (pright) // merge with right sibling {mergechild (pnode, I );}} recursive_remove (pchildnode, key) ;}t getpredecessor (node * pnode) // find the front-end Key word {While (! Pnode-> isleaf) {pnode = pnode-> pchild [pnode-> keynum];} return pnode-> keyValue [pnode-> keyNum-1];} t getsuccessor (node * pnode) // find the subsequent keyword {While (! Pnode-> isleaf) {pnode = pnode-> pchild [0];} return pnode-> keyValue [0];} PRIVATE: node * m_proot; // root node of tree B };

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.