2-3-4 trees of data structures and algorithms 06

Source: Internet
Author: User

2-3-4 trees of data structures and algorithms 06

From the analysis in section 4th, we can see that the Binary Search Tree is a good data structure, which allows you to quickly find a data item with a given keyword and quickly insert and delete data items. However, the binary search tree has a very troublesome problem. For example, if random data is inserted in the fruit tree, the execution is very good. However, if the inserted data is ordered or backward, therefore, the execution speed of the binary search tree becomes very slow. When values are inserted in an ordered manner, the binary tree is unbalanced, and its ability to quickly search, insert, and delete specified data items is lost.

2-3-4 is a multi-Cross Tree. Each node has up to four subnodes and three data items. Like the red-black tree, tree 2-4 is also a balance tree, which is slightly less efficient than the red-black tree, but easy to program. 2, 3, and 4 in the 2-3-4 tree name indicate the number of subnodes that a node may contain. There are three possible scenarios for non-leaf nodes:

· A node with one data item always has two subnodes;

· Nodes with two data items always have three subnodes;

· Nodes with three data items always have four byte points.

In short, the child node of a non-leaf node is always 1 more than the data items it contains. As shown in:

 

For convenience, use 0 to 2 to numbers the data items, and use 0 to 3 to numbers the subnode chains. A very important aspect of the tree structure is the relationship between its chain and the key values of its own data items. If the value of all the keywords in a binary tree is smaller than the value of a node, the left subnode of this node is the root subtree, all nodes with a keyword value greater than the value of a certain node or another node are in the Child tree with the right subnode as the root node. The rules in the tree are the same, and the following points are added:

· The keyword value of all subnodes In the subtree whose root is child0 is smaller than key0;

· The key value of all subnodes In the subtree whose root is child1 is greater than key0 and less than key1;

· The keyword value of all subnodes In the subtree whose root is child2 is greater than key1 and less than key2;

· The root is the Child tree of child3. The key value of all child nodes is greater than key2.

As shown in this relationship, duplicate keyword values are generally not allowed in 2-3-4 trees, so you do not need to consider comparing the same keyword values.

It is sometimes relatively simple and complicated to insert nodes into a tree from 2 to 3 to 4. When a node is not fully loaded, it is very easy to insert it. After finding a proper leaf node, you just need to insert a new data item. insertion may involve moving one or two other data items in a node, in this way, after a new data item is inserted, the key value remains in the correct order. For example:

 

If the path for finding the location to be inserted is full, insertion becomes complicated. In this case, the node must be split. This split process ensures the tree balance. Set the data items in the node to be split to A, B, and C. The following figure shows the splitting situation (assuming that the split node is not the root node ):

· Create a New empty node, which is the brother of the node to be split, on the right of the node to be split;

· Move data item C to the new node;

· Data item B is moved to the parent node of the node to be split;

· Data item A is retained in the original position;

· The rightmost two subnodes are disconnected from the node to be split and connected to the new node.

Shows the process of splitting a node. Another way to describe node splitting is to say that 4-nodes are changed to two 2-nodes.

 

If you encounter a full root when looking for the insertion point at the beginning, the insertion process is more complex:

· Create a New Root. It is the parent node of the node to be split;

· Create a second node. It is the sibling node of the node to be split;

· Data item C is moved to the new sibling node;

· Data item B is moved to the new root node;

· Data item A is retained in the original position;

· The two subnodes on the far right of the split node are disconnected and connected to the new sibling node.

Is the root split process. A new root is higher than the old one, so the height of the entire tree is increased by a layer.

 

The following code is a 2-3-4 tree:

Public class Tree234 {private Node2 root = new Node2 (); public int find (long key) {Node2 currentNode = root; int childNumber; while (true) {if (childNumber = currentNode. findItem (key ))! =-1) {return childNumber;} else if (currentNode. isLeaf () {return-1;} else {currentNode = getNextChild (currentNode, key) ;}}// insert a DataItempublic void insert (long data) {Node2 currentNode = root; DataItem tempItem = new DataItem (data); while (true) {if (currentNode. isFull () {split (currentNode); // if node is full, split itcurrentNode = currentNode. getParent (); // back upcurrentNode = getNextChild (curre NtNode, data); // search once} else if (currentNode. isLeaf () {// if node if leafbreak; // go insert} else {currentNode = getNextChild (currentNode, data) ;}} currentNode. insertItem (tempItem);} // display treepublic void displayTree () {recDisplayTree (root, 0, 0);} public Node2 getNextChild (Node2 currentNode, long key) {int j; // assumes node is not empty, not full and not leafint numItems = currentNode. getNumIte MS (); for (j = 0; j <numItems; j ++) {if (key <currentNode. getItem (j ). dData) {return currentNode. getChild (j) ;}return currentNode. getChild (j);} public void split (Node2 currentNode) {// assumes node is fullDataItem itemB, itemC; // stores the last two DataItemNode2 parent, child2, child3 nodes to be split; // store the parent node of the node to be split and the last two childint itemindexes; itemC = currentNode. removeItem (); itemB = currentNode. removeItem (); // remove items from this Nodechild2 = currentNode. disconnectChild (2); child3 = currentNode. disconnectChild (3); // remove children from this nodeNode2 newRight = new Node2 (); // make a new nodeif (currentNode = root) {root = new Node2 (); // make a new rootparent = root; // root is our parentroot. connectChild (0, currentNode); // connect currentNode to parent} else {parent = currentNode. getParent ();} // deal with parentitemIndex = pare Nt. insertItem (itemB); // insert B to parentint n = parent. getNumItems (); // total itemsfor (int j = n-1; j> itemIndex; j --) {Node2 temp = parent. disconnectChild (j); parent. connectChild (j + 1, temp);} parent. connectChild (itemIndex + 1, newRight); // deal with newRightnewRight. insertItem (itemC); newRight. connectChild (0, child2); newRight. connectChild (1, child3);} public void recDisplayTree (Node2 thisNode, int leve L, int childNumber) {System. out. print ("level =" + level + "child =" + childNumber + ""); thisNode. displayNode (); // call ourselves for each child of this nodeint numItems = thisNode. getNumItems (); for (int j = 0; j <numItems + 1; j ++) {Node2 nextNode = thisNode. getChild (j); if (nextNode! = Null) {recDisplayTree (nextNode, level + 1, j);} else continue ;}}// data item class DataItem {public long dData; public DataItem (long data) {dData = data;} public void displayItem () {System. out. print ("/" + dData) ;}// node class Node2 {private static final int ORDER = 4; private int numItems; // indicates how many data items are stored on the node: private Node2 parent; private Node2 childArray [] = new Node2 [ORDER]; // stores the array of child nodes, up to four subnodes: private DataItem itemA Rray [] = new DataItem [ORDER-1]; // an array of data items stored in the node. Each node can store up to three data items. // connect to the subnode public void connectChild (int childNum, node2 child) {childArray [childNum] = child; if (child! = Null) {child. parent = this ;}}// disconnect from the subnode and return the public Node2 disconnectChild (int childNum) {Node2 tempNode = childArray [childNum]; childArray [childNum] = null; return tempNode;} public Node2 getChild (int childNum) {return childArray [childNum];} public Node2 getParent () {return parent ;} public boolean isLeaf () {return (childArray [0] = null);} public int getNumItems () {return numItems;} public DataItem getItem (int index) {return itemArray [index];} public boolean isFull () {return (numItems = ORDER-1);} public int findItem (long key) {for (int j = 0; j <ORDER-1; j ++) {if (itemArray [j] = null) {break;} else if (itemArray [j]. dData = key) {return j ;}} return-1 ;}public int insertItem (DataItem newItem) {// assumes node is not fullnumItems ++; long newKey = newItem. dData; for (int j = ORDER-2; j> = 0; j --) {// start on rightif (itemArray [j] = null) {// item is nullcontinue; // get left one cell} else {// not nulllong itsKey = itemArray [j]. dData; // get its keyif (newKey <itsKey) {// if it's biggeritemArray [j + 1] = itemArray [j]; // shift it right} else {itemArray [j + 1] = newItem; // insert new itemreturn j + 1; // return index to new item }}itemarray [0] = newItem; return 0;} public DataItem removeItem () {// assumes node not emptyDataItem tempItem = itemArray [numItems-1]; // save itemitemArray [numItems-1] = null; // disconnect itnumItems --; return tempItem;} public void displayNode () {for (int I = 0; I <numItems; I ++) {itemArray [I]. displayItem ();} System. out. println ("/");}}

Like the red-black tree, 2-3-4 trees also need to access a node on each layer, but 2-3-4 trees are shorter than the red-black tree with the same data items (with fewer layers ). In particular, each node in the 2-3-4 tree can have up to four subnodes. If each node is full, the height of the tree should be proportional to log4N. The base-2 logarithm is 2 different from the base-4 logarithm. Therefore, when all nodes are full, the height of 2-4-4 trees is generally the height of the Red-black tree. However, they cannot all be full. The height of 2-3-4 trees is roughly between log2 (N + 1) and log2 (N + 1)/2.

On the other hand, each node has more data items to view, which increases the search time. Because linear search is used to view data items in a node, the increase in search time is proportional to M, that is, the average number of data items in each node. The total search time is proportional to M * log4N. Some nodes have 1 data item, some have 2 data items, and some have 3 data items. If two data items are calculated on average, the query time is proportional to 2 * log4N.

Therefore, increasing the number of data items on each node in the 2-3-4 tree can reduce the height of the tree. The search time in the 2-3-4 tree is roughly the same as that in the balanced binary tree (such as the red-black tree), and they are all O (logN ).



Related Article

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.