Introduction to the algorithm 18th Chapter study Questions 18-2 2-3-4 tree link and split, extended to B-Tree __ algorithm

Source: Internet
Author: User
Tags prepare

Topic

2-3-4 Tree is a special case of B-tree, it is a B-tree with degrees 2. In the B-tree blog, we implemented the B-tree is a template, so to get the 2-3-4 tree, the degree of 2 B-tree is very easy, as long as the declaration can be--btree<int,2> BT, where int is the type of stored elements.

In this subject, to achieve is the 2-3-4 tree link and split. See the red and black tree connection operation we are not difficult to get the 2-3-4 tree link method. Now, our link to the 2-3-4 tree is also promoted, that is, to achieve any degree of link and split B-tree.

(a)

There are only two ways to change the height of a B-tree: When inserting a keyword, root node full, then it will split, the tree is tall; second, when the keyword is deleted, the keyword is not in the node, the root node has only one keyword, and the child has reached the minimum number of key words, then will merge the root of the only key word and left and right children, The tree height will be reduced by 1.

Therefore, after the node increases the height field. When the tree grows taller in insert, set the height of the new root to the old roots high plus 1 (root->height = p->height + 1;) code see the B-tree implementation, the same below; in the Erase_aux function, the code does not have to change because the old root is released, pointing directly to the child, The child will become the new root.


(b) Suppose the tree T ' link to the tree T, the link keyword is k, and satisfies the condition arbitrarily key[t] < K < key[t '],key[t] > K > key[t '] is similar.

To facilitate discussion, first throw the correlation function name. Nodeatrightofheight (size_t h): The father of the rightmost node with a height of H is found in the tree T; Nodeatleftofheight (size_t h): The father of the leftmost node with a height of H is found in the tree T; Linkatright (k , T '): Connecting T ' and K linkatleft (K,t ') on the right side of the tree T: Link t ' and K to the left of the tree T.

If the tree T is higher than t ',

1, call the Nodeatrightofheight on the right side of the tree t find the same node as the tree T ';

2, in the search process, for the full node, that is, the number of keywords has reached the 2*degree-1 node, to its call split function to be split;

3, find the node of the father, and then directly into the parent node K, as the last keyword, the tree T ' whole as K's right child, complete the merge. The parent node cannot be full, as long as the full node is split.

If the tree T is the same height as T ',

1, constructs the new root, inserts the key word K, will t,t ' respectively as this node's left and right child, updates the related domain, merges completes.

The above two situations call linkatright;

If the tree T is shorter than t ',

1, exchange two trees;

2. Call Linkatleft to link the switched tree T ' and K from the left to the switched tree T, the process is symmetric with the first.


Time Complexity Analysis:

Obviously, for the 2-3-4 tree, the height of the tree is O (LGN), so the number of lookups per descent is O (LGN). For every time, even if there is a split in the case to call the Split function, because the key word is up to 3, so the split function of the For loop iteration number is not more than 1, equivalent to No loop, and at the time of insertion, if the right connection, then directly update two related fields, if the left link, You can move up to two keywords without affecting the incremental time, so each time is O (1), so the total time is O (LGN).

The above procedure will post the code later.


(c) In the process of locating a keyword K, the lookup path (find path) divides the entire tree into two sets and some keywords, and we discuss it in the following illustration, looking for the keyword K as an example, each time finding the first keyword that is not less than K at the current node. Or when the key for that node gets the maximum keyword for a K-hour.

Original 2-3-4 tree structure:


First time:

1, get the key word D, index 0;

2, in D division of the tree, because the D than k small, you want to continue to look right, get set S ' tree. The result diagram is as follows:

Figure meaning:

1, Curr represents the node currently being inspected;

2, blue to represent the split out of the set S ' elements, is the key word is smaller than K 2-3-4 tree, Small_link_key to represent the collection of key words split;

3, Red Arrows indicate the next direction to be checked (node);


Second time:

1, get the key word m, index is 1;

2, in M place the subtree splits, because M is bigger than K, then must look to the left, obtains the set S ' "a tree. The results are as follows:

Figure meaning:

1, the red Arrow refers to or this node, indicating that you want to continue to check the node;

2, Gray Green to represent the division of the set S ' ' Tree, is the key word is larger than k tree, Big_link_key expressed the resulting keyword set;


Third time:

1, get the key word F, index 0;

2, in the F Division of the subtree, because F than k small, then to the right to find, get a set of S ' tree, similar to the first time. The result diagram is as follows:

Figure meaning:

1, S ' has already had two elements, the keyword collection also already has two elements;


Fourth time:

1, get the key word K, index is 1;

2, the subtree from K division, find the required keywords, and get two trees, belong to s ' and S '. The result diagram is as follows:

Figure meaning:

1, to the end of this division, set S ' has three elements, the key word set has two elements;

2, the set S ' has two elements, the keyword collection has an element.


Note : You do not need to update the Curr after the second split, but you need to update Curr when you search for the right. This is my understanding, only in this way to ensure the right division, do not know that friends have no other way.


According to the above analysis it is not difficult to get (c) the answer:

1, height[ti-1 '] = Height[ti '] or height[ti '] + 1;

2, as above. For any y belong to Ti-1 ' and Z belong ti ', have y > Ki > Z.


(d)

1, about how to achieve division no longer repeat, the above diagram is very clear, and later give the code;

2, in the next implementation, for the continuous division, each generation of a set S ' or S ' tree we combine it with the corresponding keyword to ensure that only one tree in each set is split and the edges are merged, and the process is splittree, returning two Trees T ' and t '.


The implementation code is as follows, with the following conventions:

1, all posted too much, only to post the relevant code, please refer to B-tree. In addition to increasing height and its maintenance, the B-tree implementation also has the following three minor modifications;

2, B-tree implementation of the split function slightly modified to increase the return value, return the new node New_child address, which is a modified place;

3, Nodeatrightofheight, nodeatleftofheight and inset will handle the root full situation, so the code is packaged into a function rootfull,b tree to implement the modified second place;

4. The B-Tree adds a constructor, which is private, and is used only by node* to construct the child B-tree.


B-Tree new function declaration on linking and splitting:

Private:
	node* nodeatrightofheight (size_t);
	node* nodeatleftofheight (size_t);
	void Linkatright (const t&, btree&);
	void Linkatleft (const t&, btree&);
	void Linktwotrees (Btree &lhs, const T &link_key, Btree &rhs)
	{
		if (Lhs.empty ())
		{
			lhs.root = Rhs.root;
			Rhs.root = nullptr;
		}
		else Lhs.link (Link_key, RHS);
	}
	void Rootfull ()
	{
		node *p = root;
		root = new node;//tree will grow taller
		root->child[0] = p;
		Root->height = p->height + 1;
		Root->leaf = false;
		Split (root, 0);//root splitting
	}
	explicit Btree (node *r): Root (R), compare (R->compare) {}//is invoked only in split functions, private
Public:
	void link (const t&, btree&);//tree connection, this is a forwarding function
	void splittree (const t&, Btree& &);//Tree Division

The following are the specific implementations of the above functions:

Template <typename t,int degree,class Compare = less<t>> node<t, degree, compare>* btree<t, degree, C Ompare>::nodeatrightofheight (size_t h) {///Find the father of the rightmost node of the given height or, when the tree is H, return to the root, prepare for the right merge of the tree, and drop the search for the full node to split if (root->
	num = = node::max_num)//If the root node is full rootfull ();
	Node *curr = root; if (curr->height = = h) Return curr;//Jogen is the node while (curr->child[curr->num]->height!= h) {//always looking to the right bottom if (cu Rr->child[curr->num]->num = = node::max_num)//If the right child full Curr = Split (Curr, Curr->num);/Then split, modify the Split function,
	Make it return to the new child address else Curr = curr->child[curr->num];
return curr; Template <typename T, int degree, class Compare = Less<t>> node<t, degree, compare>* btree<t, Degr EE, compare>::nodeatleftofheight (size_t h) {//Find the father of the leftmost node of the given height, prepare for the left merge of the tree, and fall when searching for full nodes to be split if (Root->num = node::
	Max_num)//If the root node is full rootfull ();
	Node *curr = root; while (curr->child[0]->height!= h) {//go to the bottom right to find if (Curr->child[0]->num = = Node::mAx_num)//If the most right child full split (Curr, 0);//Split Curr = curr->child[0];
return curr; } template <typename t,int degree,class Compare = less<t>> void btree<t, Degree, compare>::linkatright (
	Const T &k, Btree &rhs) {node *curr = nodeatrightofheight (rhs.root->height);
		if (Curr = = Root && curr->height = = rhs.root->height) {//If two trees are just as high as Root = new node;
		Root->insert (k);
		Root->child[0] = Curr;
		ROOT-&GT;CHILD[1] = Rhs.root;
		Root->height = curr->height + 1;
	Root->leaf = false; else {//otherwise, insert key K directly into the Curr, and then point the right child pointer to the merged tree.
		Because the way to split down, Curr cannot be full curr->insert (k);
	Curr->child[curr->num] = Rhs.root; } template <typename T, int degree, class Compare = less<t>> void btree<t, Degree, compare>::linkatle
	ft (const T &k, Btree &lhs) {node *curr = nodeatleftofheight (lhs.root->height);
	Curr->insert (k); for (int i = curr->num-1; i >= 0;-I.) Curr->child[i + 1] = curr->child[I];
Curr->child[0] = Lhs.root;  } template <typename t,int degree,class Compare = less<t>> void btree<t, Degree, compare>::link (const T &k, Btree &linkedtree) {//connection forwarding function, forwarded in the following four cases. If two trees are not empty if (compare (This->root->key[0], k) && compare (k,linkedtree.root->key[0)) {//1, Arbitrary key[this] < K < Key[linkedtree]. Here the root of the No. 0 keyword is just a distinction between what kind of connection,//We assume that the given keyword and tree satisfies the above relationship, the same as if (This->root->height >= linkedtree.root->height)//1.1 The tree is higher or as high as the Linkatright (k, linkedtree);//is connected to the right of this tree else {//1.2 Otherwise the tree is shorter than swap (root, linkedtree.root);//Exchange Two tree Li Nkatleft (k, linkedtree);//On the left of the new Tree Connection}} else if (compare (linkedtree.root->key[0), K) && compare (K, This-&gt ; root->key[0]) {//2, Key[this] > K > Key[linkedtree] if (Linkedtree.root->height < This->root->hei ght)//2.1 If the tree is high linkatleft (k, linkedtree);//The left side of the tree is connected else {//2.2 Otherwise the tree is shorter or as high as the connected tree (root, linkedtree.root); Exchange of two tree linkatright (k, linkedtree);/On the right side of the new tree} else {cout << "Error:bad input!" << Endl;
	Return
} linkedtree.root = nullptr; } template <typename t,int degree,class Compare = less<t>> node<t, degree, compare>* btree<t, Degree
	, Compare>::underfillsplit (node *curr, int index) {//Is not full split, divides the Curr node from the index at node *new_child = new node;
	for (int i = index + 1; i < curr->num; ++i)//Key to new node after moving index new_child->key[i-index-1] = curr->key[i]; if (!curr->leaf) {//If it is not a leaf for (int i = index + 1; I <= curr->num; ++i) I will also move the child pointer new_child->child[i-
	INDEX-1] = curr->child[i];
	} New_child->num = curr->num-index-1;
	New_child->leaf = curr->leaf;
	New_child->height = curr->height;
	Curr->num = curr->num-new_child->num-1;
return new_child; Template <typename T, int degree, class Compare = less<t> > void Btree<t,degree,compare>::splittree (c Onst T &k, Btree &smalltree,btree &bigTree) {//To find the key word K of the path p split trees, the set of less than K merged into Smalltree, large merged into Bigtree. 	We assume k exists node *curr = root;
	root = nullptr;
	T Small_link_key = t (), Big_link_key = t ();
		while (true) {//index is the first keyword index in curr that is not less than K, or curr The last keyword index of all keywords than k-hour, but this does not affect splitting int index = Curr->search (k);
		T temp = curr->key[index]; Node *new_node = underfillsplit (Curr, index);//split the node, return the newly generated node address if (New_node->num = = 0) {//Jovin node does not have a keyword node *r = n
			Ew_node;
			New_node = new_node->child[0];
		Delete R;
			} if (Curr->num = = 0) {//If the current node does not have the keyword nodes *r = curr after splitting;
			Curr = curr->child[0];
		Delete R; if (compare (k, temp)) {//if k is less than the index keyword, go to the left, where we no longer update curr, let it continue looping at that point Linktwotrees (Bigtree, Big_link_key, Btree (new
			_node)); Big_link_key = temp;//Note this time the split keyword, in case the next time to use} else if (compare (temp, k)) {//otherwise if k is greater than the index keyword, then go to the right, this is a special situation, when the node keyword all than the K-hour
			Sheng Linktwotrees (smalltree, Small_link_key, Btree (Curr));
			Small_link_key = temp;
	Curr = new_node;//Update Curr} else {//if equal, that is already split, then merge left and right trees, end		if (Curr!= nullptr)//If Curr is a leaf, and if the above if statement (which satisfies NUM 0) is processed,//The Curr should be empty and you do not need to merge Linktwotrees (Smalltree, Small_link
			_key, Btree (Curr));
			if (New_node!= nullptr)//ditto linktwotrees (Bigtree, Big_link_key, Btree (New_node));
		Break }
	}
}


The following are examples of tests:

int main ()
{
	btree<char,2> bt,small,big;
	Vector<char> Cvec = {' P ', ' C ', ' M ', ' T ', ' X ', ' A ', ' B ', ' D ', ' E ', ' F ', ' J ', ' K ', ' L ', '
		N '};
	for (size_t i = 0; I!= cvec.size (); ++i)
		Bt.insert (cvec[i));
	cout << "Original B tree------------" << Endl;
	Bt.sequentialprint ();
	Bt.splittree (' F ', small, big);
	/*bt.splittree (' B ', small,big);
	Bt.splittree (' D ', small, big);
	Bt.splittree (' A ', small, big); * *
	cout << "Small-----------------------" << Endl;
	Small.sequentialprint ();
	cout << "Big-------------------------" << Endl;
	Big.sequentialprint ();
	GetChar ();
	return 0;
}


In the fourth Test example above Bt.splittree (' A ', small, big), the final small tree is empty, and that's true; but the big tree doesn't have the keyword B. This is because B is the last element of the set S ' corresponding keyword set, split at a to form two empty trees, so the last one cannot be merged, so the big tree has no keyword B, which is also true. Because the merge operation cannot merge an empty tree, the keyword will have no children, which does not conform to the nature of the B-tree.

Other tests are also correct, and they are correct for other degrees, so it's a true B-tree split and link, not just a 2-3-4 tree.


At last, we give the running screenshot of the first example above:




 

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.