From the previous introduction, we know that in a binary tree, each node has only one data item, with a maximum of two child nodes. If you allow each node to have more data items and more child nodes, it is a multi-fork tree. This blog we will introduce the--2-3-4 tree, which is a multi-fork tree, with a maximum of four child nodes and three data items per node.
1, 2-3-4 Tree Introduction
2-3-4 Tree Each node has a maximum of four byte points and three data items, the number of 2,3,4 in the name means the number of child nodes that a node may contain. There are three possible scenarios for non-leaf nodes:
①, a node with a data item always has two sub-nodes;
②, a node with two data items always has three sub-nodes;
③, a node with three data items always has four sub-nodes;
In short, the number of child nodes of a non-leaf node is always 1 more than the data item it contains. If the number of child nodes is L and the number of data items is D, then: L = d + 1
A leaf node (the bottom row) is not a child node, but it may contain one, two, or three data items. An empty node does not exist.
The important point in the tree structure is the relationship between the key value sizes of the nodes. In a binary tree, all nodes with a key value that are smaller than a node's value are on a subtree of the root of the left child node of the node, and all nodes with a greater value than a node value are on the subtree of the root of the right child node of the node. The 2-3-4 tree rules are the same, and add the following points:
To facilitate the description, use numbers from 0 to 2 to number the data items, numbering the child nodes with 0 to 3 digits, such as:
①, Root is the child0 of all child nodes of the subtree of the keyword value is less than key0;
②, Root is the child1 of all child nodes of the subtree with the key value greater than key0 and less than key1;
③, Root is the child2 of all child nodes of the subtree with the key value greater than key1 and less than key2;
④, Root is the child3 of all child nodes of the subtree with a key value greater than key2.
Simplified relationships For example, because the 2-3-4 tree generally does not allow duplicate key values, you do not have to consider the same situation when comparing key values.
2, Search 2-3-4 tree
A data item that looks for a specific keyword value is similar to a search in a binary tree. Search from the root node, unless the keyword value is the root, select the appropriate range for the keyword value, and turn to that direction until you find it.
For example, for the following image, we need to look up a data item with a keyword value of 64.
First, starting from the root node, the root node has only one data item 50, not found, and because 64:50 is large, then go to the child node of the root node child1. 60|70|80 also did not find, and 60<64<70, so we still find the node of the child1,62|64|66, we found its second data item is exactly 64, and then found.
3. Insert
The new data items are usually inserted in the leaf node, at the bottom of the tree. If you insert into a node that has child nodes, the number of child nodes changes to maintain the structure of the tree because the nodes in the 2-3-4 tree are 1 more children than the data items.
Insert operations are sometimes simple and sometimes complex.
①, when inserting a node without a full data item is very simple, to find the appropriate location, only need to insert new data items to be able to, insert may involve moving one or the other two data items in one node, so that the new data items inserted after the keyword values remain in the correct order. Such as:
②, if the node is full when looking down on the way to the insertion position, then the insertion becomes complicated. When this happens, the nodes must be split, and splitting can guarantee the balance of the 2-3-4 tree.
PS: The top-down 2-3-4 tree is discussed here, because the node splits in the path where the insertion point is found down. To set the data item to be split to A,b,c, the following is the case of node splitting (assuming that the split node is not the root node):
1. Node splitting
First, create a new empty node, it is to split the node's brother, on the right to split the node;
Second, the data item C is moved to the new node;
Third, the data item B is moved to the parent node of the node to be split;
Iv. data item A remains in its original position;
V. The rightmost two sub-nodes are disconnected from the division and connected to the new node.
Describes the example of node splitting, and another way of describing node splitting is that 4-node becomes two 2-node. Node splitting is the movement of data up and to the right, thus maintaining a balance of numbers. The general insertion requires splitting only one node, which requires multiple splits unless there is more than one full node on the insert path.
2, the root of the division
If you encounter a full root node when you first look up the insertion node, the insertion process is more complex:
①, creates a new root node, which is the parent node of the node to be split.
②, create a second new node, it is to split the nodes of the sibling node;
③, data item C is moved to the new sibling node;
④, data item B is moved to the new root node;
⑤, data item A remains in its original position;
⑥, two sub-nodes to the right of the split node are disconnected and connected to the new sibling node.
is the root division, the height of the whole tree is added 1 after the split is complete. Another way to describe root splitting is to say that 4-node becomes three 2-node.
Note: When inserting, when encountering a node that is not full, continue looking down on its child nodes for insertion. If the node is inserted directly, then the child nodes will be increased, because the number of child nodes in the 2-3-4 tree is 1 more than the data item, and if the inserted node is full, then the node splitting is necessary. is a series of insertions, 4 nodes split, two are roots, two are leaf nodes:
4. Complete source Code implementation
It is divided into node class nodes, which represent the data item class DataItem of each node, and the last 2-3-4 tree class Tree234.class
Package Com.ys.tree.twothreefour;public class Tree234 {private Node root = new node ();/*public Tree234 () {root = new node ( );} *///Lookup keyword Value public int find (long key) {Node Curnode = Root;int Childnumber, while (true) {if (Childnumber = Curnode.finditem ( Key)!=-1) {return childnumber;} else if (Curnode.isleaf ()) {//node is a leaf node return-1;} Else{curnode = Getnextchild (Curnode,key);}} Public Node getnextchild (node Thenode,long thevalue) {int J;int NumItems = Thenode.getnumitems (); for (j = 0; J < Numitem s; J + +) {if (Thevalue < Thenode.getitem (j). DData) {return thenode.getchild (j);}} Return Thenode.getchild (j);} Insert data item public void Insert (long dvalue) {Node Curnode = Root;dataitem Tempitem = new DataItem (Dvalue), while (true) {if ( Curnode.isfull ()) {//If the node is full of data items, split node split (curnode); curnode = Curnode.getparent (); curnode = Getnextchild (Curnode, Dvalue);} else if (Curnode.isleaf ()) {//The current node is a leaf node break;} Else{curnode = Getnextchild (Curnode, Dvalue);}} End Whilecurnode.insertitem (Tempitem);} public void Split (Node thisnode) {DataItem ITEMB,ITEMC; Node Parent,child2,child3;int ITEMINDEX;ITEMC = Thisnode.removeitem (); itemb = Thisnode.removeitem (); child2 = Thisnode.disconnectchild (2); child3 = Thisnode.disconnectchild (3); Node Newright = new node (), if (Thisnode = = root) {//If the current node is the root node, execute root Split root = new node ();p arent = root;root.connectchild (0, Thi SNode);} Else{parent = Thisnode.getparent ();} Handle parent Node ItemIndex = Parent.insertitem (itemb); int n = Parent.getnumitems (); for (int j = n-1; j > itemIndex; j--) {Node tem p = Parent.disconnectchild (j);p Arent.connectchild (j+1, temp);} Parent.connectchild (itemindex+1, newright);//Process New Right node Newright.insertitem (ITEMC); Newright.connectchild (0, Child2) ; Newright.connectchild (1, child3);} Print tree node public void DisplayTree () {recdisplaytree (root,0,0);} private void Recdisplaytree (Node thisnode,int level,int childnumber) {System.out.println ("levle=" +level+ "child=" + Childnumber+ ""); Thisnode.displaynode (); int numitems = Thisnode.getnumitems (); for (int j = 0; J < Numitems+1; J + +) {Node NextNode = ThisnoDe.getchild (j); if (nextnode! = null) {Recdisplaytree (NextNode, Level+1, j);} Else{return;}}} Data item class Dataitem{public long Ddata;public DataItem (long dData) {this.ddata = DData;} public void Displayitem () {System.out.println ("/" +ddata);}} The node class node{private static final int ORDER = 4;private int numitems;//Indicates how many data items the node has. Private node parent;//parent private Node childarray[] = new node[order];//An array of child nodes, with a maximum of 4 child nodes private DataItem itemarray[] = new dataitem[order-1];//An array of data items to store, A node has a maximum of three data items//connection subnodes public void connectchild (int childnum,node children) {Childarray[childnum] = child;if (child! = null) { Child.parent = this;}} Disconnects the child node and returns the child node public, node disconnectchild (int childnum) {node Tempnode = childarray[childnum];childarray[ Childnum] = Null;return tempnode;} Get a child of node public node getchild (int childnum) {return childarray[childnum];} Gets the parent node, public, node GetParent () {return parent;} Determine if the leaf node public boolean isleaf () {return (childarray[0] = = null)? True:false;} Gets the number of node data items public int getnumitems () {return numiteMS;} Get a data item for a node public DataItem getItem (int index) {return itemarray[index];} Determines whether the node's data item is full (up to 3) public Boolean isfull () {return (NumItems = = ORDER-1)? True:false;} Locate the position of the data item in the node 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;} Inserts a data item into the node public int insertitem (DataItem newitem) {Numitems++;long NewKey = newitem.ddata;for (int j = ORDER-2; J >= 0 ; j--) {if (itemarray[j] = = null) {//If empty, continue forward loop continue;} Else{long Itskey = itemarray[j].ddata;//The data item at a location of the Save node if (NewKey < Itskey) {//if Pinue inserted data item large itemarray[j+1] = Itemarray[j] ;//Move the Big data item backward one}else{itemarray[j+1] = newitem;//If the Pinue inserted data item is small, insert the return j+1 directly;}} If both are empty, or are larger than the data item to be inserted, place the data item you want to insert in the first position of the node itemarray[0] = Newitem;return 0;} Data entry for the removed node public DataItem RemoveItem () {DataItem temp = itemarray[numitems-1];itemarray[numitems-1] = null;numitems--; return temp;} All data items of the print node public void Displaynode () {for (int j = 0; J < NumItems; J + +) {Itemarray[j].dispLayitem ();} System.out.println ("/");}}}
5.2-3-4 Tree and Red black tree
The 2-3-4 tree is a multi-forked tree, and the red and black trees are two forks, which may look completely different, but in a sense they are exactly the same, one that can be changed by applying some simple rules to another, and keeping them balanced, mathematically called them isomorphic.
①, corresponding rules
Use the following three rules to convert a 2-3-4 tree to a red-black tree:
First, each 2-node in the 2-3-4 tree is transformed into a red-Haishi black node.
Second, each 3-node into a child node and a parent node, the child node has two of its own child nodes: W and x or X and Y. The parent node has another child node: Y or W. It doesn't matter which node becomes a child node or parent node. The child nodes are painted red and the parent node is painted black.
Three, each 4-node into a parent node and two child nodes. The first child node has its own child nodes W and X, and the second child node has child nodes Y and Z. As before, the child nodes are painted red and the parent node is painted black.
is a 2-3-4 tree transformed into a corresponding red-black tree. The dotted-line subtree is made up of 3-node and 4-node. After conversion conforms to the red-Haishi rule, the root node is red, two red nodes are not connected, the number of black nodes on each path from root to leaf node is the same.
②, Operation equivalence
Not only the red-Haishi structure corresponds to the 2-3-4 tree, but also the two tree operations. The 2-3-4 tree is balanced with node splits, and red-Haishi is balanced with color transformations and rotations.
is 4-node splitting. The part of the dashed line is equivalent to the 4-node. After the color transformation, 40, 60 nodes are black, and 50 nodes are red. Therefore, node 50 and its parent node 70 are for the 3-node, as shown in the dashed line.
6, the efficiency of 2-3-4 tree
Analysis of the 2-3-4 tree we can compare with the red and black trees. The number of layers of red-Haishi (Balanced binary tree) is approximately log2 (n+1), while the 2-3-4 tree can have up to 4 data items per node, if the nodes are full, then the height and log4n. So when all the nodes are full, the 2-3-4 tree is roughly half the height of red-Haishi. But they can't all be full, so the height of the 2-3-4 tree is roughly log2 (n+1) and log2 (n+1)/2. Reducing the height of the 2-3-4 tree makes it shorter to find than red-Haishi.
On the other hand, each node has more data items to view, which increases the lookup time. Because a linear search is used in a node to view data items, the multiple of the lookup time is proportional to M, which is the average number of data items per node. The total lookup time is proportional to the m*log4n.
Java Data structures and algorithms (12)--2-3-4 Tree