Based on the definition of AVL tree, this paper deduces the scheme of the AVL tree rotation, which is carried out on the premise that the definition of AVL tree has been clearly known . The article focuses on the process of thinking, and does not directly give the AVL tree is how to rotate, to remind oneself later in the study to pay attention to the process of deduction. In this, I want special thanks to my data structure teacher, is he let me realize the importance of thinking.
first, from the definition of the AVL tree
1. Two fork find tree problem
Binary search tree appears, although the average time to find the search dropped to Logn, but after several deletions or inserts, the root node may appear Supi the right subtree is much higher, or the right subtree is much higher than the left sub-tree. :
In this case, the search efficiency will be quite low. So the question now is: to come up with a solution that will keep the binary search tree in balance. At this point, we define a new two-fork lookup tree, which is a two-fork lookup tree with equilibrium conditions, namely the AVL tree.
2. Definition of AVL tree
An AVL tree is a 1 of the height of the right subtree of each node of the Saozi two-fork lookup tree (the height of the empty tree is defined as-1). In the left tree is the AVL tree, but the tree on the right is not.
In the right tree, the left subtree of the root node 7 has a height of 2, the right subtree has a height of 0, and the height difference is 2 for the subtree, so it is not an AVL tree.
With the definition of the AVL tree, you can begin to deduce how the AVL tree is rotated to achieve the equilibrium condition.
second, start derivation.
1. Analyze the areas that need attention.
First, we use positive thinking to analyze. Normally, when inserting, we need to update all the balance information to those nodes on the path to the root node, and the insertion operation is difficult because inserting a node might break the attributes of the AVL tree. For example, inserting 6 into the AVL tree in Figure 4-29 will break the balance condition of the node with the keyword 8. If this is the case, then it is necessary to restore the nature (that is, to restore the balance) until this step is completed.
2. Minimize the impact.
As a programmer, we always want to minimize the impact in the process of solving problems.
In the above analysis, we learned that after inserting a node, it is possible to break the balance of the AVL tree. Moreover, this destructive balancing act is likely to be a ripple effect, for example, When we add a leaf node with a keyword of 2.5 below the leaf node in the AVL tree in Figure 4-29 with a key of 3, it breaks the balance of the node with the keyword 4, and the balance of the node with the keyword 2 and the root of the keyword 5 is broken.
This chain reaction is very scary, so we have to minimize the impact. If we can stop the spread of chain reaction on the first equilibrium broken node , we can minimize the impact. Here, we make simple corrections to the local part of the tree by rotation , thus minimizing the impact.
We do not have to control how the rotation, the following will be a step-by-step deduction, the nature of rotation deduced, the wonderful content is below!
3. Assume that a node is the first balanced node that has been compromised
Let's start by analyzing all the possible scenarios.
first case: the imbalance that results from the left side of the first equilibrium broken node
The first set of K2 is the first node that does not satisfy the AVL balance feature , that is, the K2 is balanced before the new node is inserted. Then, insert the place for K2 's Zuozi:
In this case, the height of the left subtree of the K2 is 2 higher than the right subtree of the tree. Set
A. The name of the tree in Stree, as part of the entire AVL tree.
b before inserting a node , the height of the tree with K2 as the root node is h+2, that is, the height of Stree is h+2;
C. In this case, before inserting a node, the height of the left subtree of the K2 is h+1, and the height of the right subtree Z of K2 is H.
D. after inserting a node , the height of the tree with K2 as the root node becomes h+3;
E. After inserting a node, the height of the left subtree of the K2 is h+2 , and the height of the right subtree Z of K2 is still H.
The problem now is that the height of the stree will remain unchanged after inserting the new node . That is, to change the height of the stree from h+3 to h+2. In this way, there will be no chain reaction, minimizing the impact, because the height of the stree is still the height before the insertion node. From this question, we will draw a series of questions. (The problem is right, after all, the conclusion is not a sudden, to go through detailed analysis, and constantly ask why?) )
Question 1: What can be done to make Stree's height change back to h+2?
We can change the position of the node inside to achieve the purpose of changing the stree height. Note, however, that the AVL tree is first a binary lookup tree, where the node's position is regular: for each node x in the tree, all the key values in its left subtree are less than the key value of x, and all the key values in its right subtree are greater than the key value of X. Therefore, when we change the position of the node in the Stree, we do not break the above rule.
Under the numerous restrictions, we can only adjust the position of the nodes in the middle, obviously, K2 of the Supi right sub-tree height 2, so we should put K2 's left son K1 mentioned K2 position. So the height of the stree becomes the height of the K1, which changes back to the h+2. At this time, the right son of K1 is the k2,k1 of the right sub-tree Y into K2 's left subtree, such as:
Here, it has been analyzed how to rotate, and this practice seems to really solve the problem, but how to be sure that this is correct, think carefully, this situation can be subdivided:
Scenario 1: The new node is inserted in K1 's left subtree X , causing K2 to lose balance (note that the K1 is balanced and don't forget that K2 is the first imbalance).
Scenario 2: The new node is inserted in the right subtree Y of K1, causing K2 to lose balance.
Question 2: Under scenario 1, before inserting a new node, what is the height of X and y, and at such a height, is this rotation correct?
Set by the question, we already know that Z's height is h. Before inserting a node, the height of the tree with K1 as the root is h+1, so the height of X, y can be at most H. at this point, the height of x can be determined to be H, because the new node is inserted from X, so that the height of the K1 is changed from h+1 to h+2, so the height of x is h before the new node is inserted. Again to determine the height of y:
If the height of y is h-1, then after inserting a new node in X, the height of x becomes h+1, so that the height difference of x and Y becomes 2, and the first node that loses the balance is K1 instead of K2, which contradicts the hypothesis, so the height of Y is not h-1.
To here can be determined that the height of Y is also H , the only way to insert a new node in X, will not cause K1 imbalance, after all, there is a major premise there,K2 is the first unbalanced node .
Now that the height of x and Y is resolved, at this height, the rotated tree (the tree to the right of Figure 4-31), the height of x is h+1,k1 height of h+2,k2 is the height of h+1,y and Z is H. At this point the height of each node satisfies the equilibrium condition, so, in case 1, the rotation (this rotation is called single rotation ) is correct, it effectively corrects the height of the stree, so that the effect truncated in the stree, so that the whole AVL tree properties unchanged.
Question 2: Under Scenario 2, before inserting a new node, what is the height of X and y, and at such a height, is this rotation correct?
Here, the analysis of the x and Y Heights is the same as before, and after the analysis, the height of x and Y is also H. When inserted, the height of Y becomes h+1, as shown in the tree on the left of 4-34
In this case, it is not possible to follow the above rotation, so that after rotation y becomes the left subtree of the K2. At this point, the K1 is still unbalanced, so this rotation is not correct. We need to find another way to make the stree balance.
Question 3: How can i solve the problem caused by scenario 2?
The problem here is that the subtree Y is too deep, and the single rotation does not decrease its depth. In Scenario 1, we solved the problem by making a single rotation in the K2 to raise the higher subtree K1. So, we thought, since the single rotation can be higher sub-tree to carry up, then we first in the K1 place a single rotation, the y subtree up, which seems to be a good idea. Now that we're going to do a single rotation, we need a K1 right son K3, as shown in:
Here, we do not care about the height of the subtree A, B, their height will not exceed H, nor less than h-1.
We have a single rotation at the K1, the following picture is rotated:
Here, it can be seen that the stree is still unbalanced, and perhaps we have to use the same principle for a single rotation. This time, we took K3 to the position of K2 to perform multiple single rotations, as shown in the tree on the right:
At this point, the rotation is complete, easy to verify, after two rotations, the resulting tree (figure 4-35 to the right of the tree) is to meet the AVL balance characteristics, this rotation called double rotation .
Now that we've solved both cases 1 and 2, here's an accurate definition of both cases, so let's call the node athat must be rebalanced.
Case 1: an insertion is made to the left subtree of a's left son.
Case 2: Insert the right sub-tree of A's left son.
There may be some doubt as to whether these situations have been included in all cases. For example, in case 1, you also need to split the x to continue to produce the situation 3,4.....N? In fact, we just have to think of X as a whole, we just need to know that the height of the x subtree after insertion is H + 1, and does not have to care about where it was inserted.
second case: the imbalance that results from the right of the first balanced node being broken
In fact, the second case is the symmetry of the first case, just the other side of the insertion, its derivation process and the first case is the same. In the same way, there are two situations:
Set A is the node that must be rebalanced,
Case 3: Insert the left subtree of the right son of a.
Case 4: Insert the right subtree of a right son.
Here's a summary of 4 scenarios:
Case 1 and Case 4 are about the mirror symmetry of Point A, while 2 and 3 are about the mirror symmetry of point A. So theoretically there are only two cases, of course, from a programming point of view, or four cases.
The first is when inserting an "outside" condition (that is, left-left or right-right), which is adjusted by a single rotation of the tree. The second case is the insertion of an "internal" situation (i.e. left-right or right-left), which is handled by a slightly more complex double rotation (two single rotations).
3. Practical examples
Then come down and show an example. Suppose you start by inserting keywords 3, 2, and 1 from the initial empty AVL tree, and then inserting 4 through 7 sequentially. Insert Keyword 1 o'clock the first problem occurs, and the AVL feature is destroyed at the root. We implemented a single rotation correction between the root and its left son. Here are two trees before and after the rotation:
A dashed line connects the two nodes to be rotated, which are the bodies of the rotation. Here we insert a node with a keyword of 4, which is fine, but inserting 5 destroys the AVL feature at Node 3, which is corrected by a single rotation.
It is important to note that in programming, be careful to make 2 of the right son 4, otherwise it will cause 4 is inaccessible. Below we insert 6. This creates a balance problem at the root node because its Zuozi height is 0 and the right subtree height is 2. So we implement a single rotation at the root between 2 and 4.
The result of rotation makes 2 a son of 4 and 4 of the original left subtree into a new right subtree of Node 2. The next keyword We insert is 7, which causes additional rotation:
The following shows the case of a double rotation:
We now insert the keyword 10 to 16 in reverse order, then insert 8, and then insert 9. Inserting 16 is easy because it does not break the balance feature, but inserting 15 causes the node to be highly unbalanced at 7. This belongs to case 3, which needs to be solved by a right-left double rotation, this right-left double rotation will involve 7,16 and 15.
Below we insert 14, it also needs a double rotation. At this point, fix the tree's double rotation or right-left double rotation, which will involve 6, 15, and 7.
Now insert 13, then there will be an imbalance at the root. Since 13 is not between 4 and 7, we know that a single rotation can be done to fix the work.
Inserting 12 also takes a single rotation:
In order to insert 11, a single rotation is also required, and this rotation is required for the subsequent insertion of 10. We inserted 8 without rotation, thus creating an almost ideal balance tree.
Finally, we insert 9 to demonstrate a symmetric case of double rotation. Note that 9 causes the node that contains the keyword 10 to produce an imbalance. Since 9 is between 10 and 8 (8 is the son of node 9 on the path to 10), a double rotation is required.
The example ends here.
4. Code implementation
The following is the code implementation, not detailed introduction, after all, this article focuses on the derivation process:
#include <Stdio.H>#include <Stdlib.H>struct Avlnode;//node of the treetypedef struct AVLNODE*Avlpostion;//Tree pointertypedef struct AVLNODE*Avltree;//Tree pointertypedef int AVLELEMENTTYPE;//elements in a tree node#define Max(x, Y) ((X)>(Y)?(X): (Y)) struct Avlnode {avlelementtype element; Avltree left;//Left dial hand treeAvltree right;//Right sub-treeint height;//height of the tree};voidMakeavlempty (Avltree tree) {if(Tree!= NULL) {Makeavlempty (tree -left); Makeavlempty (tree -right); Free (tree); }}//Find the corresponding tree node for the keyword x, and returnAvlpostion Findavl (Avlelementtype x,avltree tree) {if(Tree== NULL){return NULL; }if(x<Tree -Element) {returnFindavl (X,tree -left); }Else if(x>Tree -Element) {returnFindavl (X,tree -right); }Else{returnTree }}//Find the smallest nodeAvlpostion Findminavl (Avltree tree) {if(Tree!= NULL) { while(Tree -left) {Tree=Tree -Left } }returnTree;}//Find the largest nodeAvlpostion Findmaxavl (Avltree tree) {if(Tree!= NULL) { while(Tree -right) {Tree=Tree -Right } }returnTree;}//Returns the height of the treestatic int height (Avlpostion p) {if(p== NULL) {return -1; }Else{returnP -Height }}/ * If K2 has a left son K1, then return K1 as root, K2 into K1 's right son, and update their height * /Static Avlpostion Singlerotatewithleft (avlpostion K2) {avlpostion K1=K2 -Left K2 -Left=K1 -Right K1 -Right=K2; K2 -Height= Max(Height (K2 -left), Height (K2 -right))+ 1; K1 -Height= Max(Height (K1 -left), K2 -Height+ 1;returnK1;}/ * If K2 has a right son K1, then return K1 as root, K2 into K1 's left son, and update their height * /Static Avlpostion Singlerotatewithright (avlpostion K2) {avlpostion K1=K2 -Right K2 -Right=K1 -Left K1 -Left=K2; K2 -Height= Max(Height (K2 -left), Height (K2 -right))+ 1; K1 -Height= Max(K2 -Height,height (K1 -right))+ 1;returnK1;} Static Avlpostion Doublerotatewithleft (Avlpostion K3) {K3 -Left=Singlerotatewithright (K3 -left);returnSinglerotatewithleft (K3);} Static Avlpostion Doublerotatewithright (Avlpostion K3) {K3 -Right=Singlerotatewithleft (K3 -right);returnSinglerotatewithright (K3);}//The most critical insertion methodAvltree Insertavl (Avlelementtype x,avltree tree) {if(Tree== NULL) {Tree=(avlpostion) malloc (sizeof (struct avlnode));if(Tree== NULL) {printf ("Create Tree fail!\n"); }Else{Tree -Element=X Tree -Left= NULL; Tree -Right= NULL; Tree -Height= 0; } }Else if(x<Tree -Element) {//If the situation is broken out of balance, then it must be Zuozi highTree -Left=Insertavl (X,tree -left);//Let next call to update tree->left; if(Height (tree -Left-Height (tree -Right== 2) {if(x<Tree -Left -Element) {//is inserted in the left subtree of the tree's left sonTree=Singlerotatewithleft (tree); }Else{//inserted in the right subtree of the tree's left sonTree=Doublerotatewithleft (tree); } } }Else if(x>Tree -Element) {Tree -Right=Insertavl (X,tree -right);if(Height (tree -Right-Height (tree -Left== 2) {if(x>Tree -Right -Element) {Tree=Singlerotatewithright (tree); }Else{Tree=Doublerotatewithright (tree); } } }//If there are equal nodes, do nothing //Update node height informationTree -Height= Max(Height (tree -left), Height (tree -right))+ 1;returnTree//Implements the purpose of updating the node that was last called}//Middle sequence traversalvoidInordertraversal (Avltree tree) {if(Tree!= NULL) {Inordertraversal (tree -left); printf"%d", tree -Element); Inordertraversal (tree -right); }}int Main () {int n; printf"Please enter a node number: \ n");if(SCANF ("%d",&N== 1) {int x; Avltree Tree= NULL; for (int i= 0; I<N I++) {if(SCANF ("%d",&X== 1) {Tree=Insertavl (X,tree); }} inordertraversal (tree); } printf ("\ n");return 0;}
At this point, the whole article will be finished!
Starting with the definition of the AVL tree, the scheme of rotation is deduced in one step.