Please believe me, 30 minutes to let you master the AVL tree (balanced binary tree)

Source: Internet
Author: User
Tags bool comparison sort

please believe me, 30 minutes to let you master the AVL tree (balanced binary tree)

Preface: This article is not suitable for a group of data 15 minutes to achieve the insertion and deletion of AVL Daniel (also please do not fight side dishes)

This article is suitable for those who do not know the AVL yet do not personally implement the INSERT and delete operations of AVL students

PS, when you mock the landlord's topic, you have proved that you are laughing at your IQ. We must be good at conquering unfamiliar things. If you have half an hour to start the mind without distractions, suggest those who read 10 minutes of the article on the heart or close the browser bar.

Article structure:


What is a two-fork sort tree (BST) binary sorting tree (binary sort trees) is also called a binary lookup tree. It is either an empty tree or a two-fork tree with the following properties: (1) The Joz tree is not empty, then the value of all nodes on the left subtree is less than the value of its root node, (2) If the right subtree is not empty, the value of all nodes on the right subtree is greater than the value of its root node, and (3) the left and right subtrees are two forks respectively;

Okay, two forks. Sort tree definition very good understanding (if not understand, in order not to waste time, first pause, go to Google or Baidu, understand and continue), then this does not give other examples, below I implement the following BST some basic operation algorithm. Basic operation of BST

typedef struct _BITNODE
{
    int data;
    struct _bitnode *lchild,*rchild;
} Bitnode,*bitree;
1.1, BST Search: Why Search first? General BST there is no duplicate elements, you add or delete elements, you must first look up, see there is no ah, so the BST search to achieve first, this search is very simple, slowly read my explanation, we first look at this picture
If you want to find a node with a value of 3 and give you the root node of the tree, you can only see this root node around the child (other permissions you see, you can not see). That is not easy, first with 3 and root node (this is 6) ratio, obviously less than 6. Then I will go to his left child than, notice, at this time 4 is the root of the left subtree of 6, then we and 4 this new root than it, obviously more than 4 small. Then we continue to find this new root of the left child than, and at this time 3 is the root of the left subtree of 4, then we and this root than, wow, we follow the clues, finally found the OH. , let's refine the process, and notice that we are comparing each other with the roots. Rule: 1. Compare with the root of this tree before 2. If it is smaller than the root of the roots of the left sub-tree than the roots, or the root of the right sub-tree than.         3. Repeat the 2 process until the root is empty. Recursive code is easy to implement based on 3 steps. Search element, parameter 0: root node, 1: Find element, 2: Find previous node pointer of target element, initial value is null
3: If you return true to the target to the element pointer to n, return false, the pre copy to n) (parameter if you do not understand, do not scrutiny, look down)
BOOL Searchbst (bitree t,int key,bitree pre,bitree&n);
BOOL Searchbst (bitree t,int key,bitree pre,bitree&n)
 {
     if (! T)
     {
         n=pre;       If this number is an empty tree, then we copy the previous element pointer pre (which is null at this time) to n and note that n is null when the tree is empty.
         return false;   return false not found
     }
     else if (key==t->data)
     {
         n=t;        When you find it, give the target element pointer n
         return true;
     if (key<t->data)
         searchbst (t->lchild,key,t,n);//Go find his Zogen than
     else
     {
         Searchbst (t-> RCHILD,KEY,T,N);//Go find his right son root ratio.
     }
 }
1.2 BST's addition element algorithm implementation has the search this function, then our added element function is very easy to implement, the algorithm description: 1. First search so that the added key, in the tree. 2. If not found, apply space, add key to the inside return true, otherwise return false.
BOOL Insetbst (Bitree &t,int k)
 {
     bitnode* p;
     if (! Searchbst (t,k,null,p))
     {   Bitnode * temp=new bitnode;
         temp->data=k;
         temp->lchild=temp->rchild=null;
         if (!p)  //Only if the tree is empty, p is null at this time. See here should understand Searchbst (t,k,pre,p) These parameters of the meaning of it
         {
           t=temp; 
         }
         else
         {if
             (k<p->data)  ///If it is not an empty tree, the added key value is compared to P, which is less than that of his left child, and no child is right child
                 p->lchild=temp;
             else
             {
                 p->rchild=temp;
             }
         }
         return 0;
     }
     else 
     {
         return false;
     }
 }
1.3BST algorithm implementation for deleting elements now that you have seen this, you have a strong curiosity, and we are not far from success in this section, so let's go ahead.
There are 3 kinds of cases, 1 have Zuozi, 2, only right subtree, 3, all the subtree. Let's look at the first type
As shown in the figure above we are going to delete the 4 node, we will point the left child of his parents node to the left subtree of 4. It's simple. Let me see the second kind.

As shown in the figure above we want to delete the 7 node only the right subtree, presumably must think of, then we put his parents node right child point to 7 node right child, that is OK, great ... Now look at the third situation.         Do you see the changes in these three pictures? We're going to remove node 4, in order to keep the tree in order we're going to look for a bigger 4 than the 4 nearest, that's his successor, of course, you can find the former is also possible. This figure is to find his successor. After we find it, replace it with the successor of 4 with 4, and finally delete the successor node. OK, everyone read and understand the 3 kinds of situations, the code implementation is very easy.
 BOOL Deleelement (Bitree&t,int key) {if (!   T) {return 0;
            If the tree is empty, return false} if (T->data==key) {bitnode*s,*p;
                 if (t->rchild==null)//Only right sub-tree, condition 2 {s=t;
                 t=t->lchild;
            Free (s);               } else if (t->lchild==null) {s=t;
                Only left dial hand trees, situation 1 t=t->rchild;
            Free (s);
                } else {//Case 3, the left and right sub-trees have p=t;
                s=t->rchild;           while (S->lchild) {p=s;
                Find the successor of the node to be removed, and that is the s=s->lchild; of his right child.    } t->data=s->data;   Delete node if (p!=t) {p->lchild=null;) with subsequent substitution of the delete node
              The right child of the deleted node is not a leaf node.  } else p->rchild=null;
            The right child of the deleted node is the leaf node free (s);
         } return 1;    } else if (key<t->data) deleelement (T->lchild,key);   Go and compare with his Zogen else deleelement (T->rchild,key); To compare with his right son's roots.
The middle sequence traverses and outputs the element
 void Inorderreverse (Bitree t)
 {
     if (t)
     {
         inorderreverse (t->lchild);
         cout<<t->data<<endl;
         Inorderreverse (T->rchild);
     }
 }
Finally finished, we also immediately on the machine to test it, if you understand, test it yourself, see if you can write it out oh. Here's my own test.
int main ()
{
    bitree tree=null;
    int a[]={60,86,50,40,35,74,51,100,37,90};
    for (int i=0;i<10;i++)
        insetbst (Tree,a[i]);
    Inorderreverse (tree);
    cout<< "             " <<endl<<endl;
    Deleelement (tree,62);
    Inorderreverse (tree);
    return 0;
}

So far the binary sorting tree has been taken care of, if you have achieved the above functions, it proves that you have a very strong curiosity and talent (because the landlord made a few days to understand, you more than 10 points on the fix, that is not the best proof of it.) PS: The landlord is kind of very dull but very perseverance), with the foundation of the front, AVL is extremely easy, do not lose heart oh, get up and continue the journey. If you do not understand, the first pause will, to avoid wasting unnecessary time, do not look down, it is recommended to carefully read a few times, if you do not understand, this article may not be suitable for you, suggest reference to other articles.
What is the AVL definition:

Balanced binary Tree definition (AVL): It is either an empty tree, or a two-prong tree with the following properties: The difference in the depth of its Saozi right subtree (balance factor) is not more than 1, and its Saozi right subtree is a balanced binary tree.

Balance factor (BF): The depth of the left subtree of the node minus the depth of the right subtree, then obviously -1<=bf<=1, here we define:

#define EH 0, #define LH 1, #define RH-1. In order of equal height, left high, right high.

typedef struct _BITNODE
{
int data;
int bf;//Balance Factor
struct _bitnode *lchild,*rchild;
}bitnode,*bitree;

As we all know, the balanced binary tree is introduced on the binary sort tree (BST) (This is very important, for example), in order to solve the imbalance of the two-fork sorting tree resulting in a significant decrease in time complexity, then AVL will maintain (BST) The best time complexity O (LOGN), So every time you insert and delete to make sure that the two fork tree balance, then how to maintain balance. If you don't understand it, look at the chart below.


Look at the charms of AVL. There is the value of its existence, see the picture below to know.
Figure I and figure two are BST, but figure two is not AVL, figure one is the AVL Tree, if we want to find 10, figure A comparison of 3, and the comparison of the number of figures is 7 times, it is obvious that the size of the larger words AVL advantage is very prominent. Since the AVL is so powerful, the cow forks. Then let's take it down. 2.1 AVL add element here Search and BST search, I do not waste time to introduce, we first implement the addition of elements, implement and then delete the elements. However, each time the insertion and deletion to ensure that the two fork tree balance, then how to maintain balance. We are introducing the equilibrium factor. Notice the definition of the equilibrium factor. I'll show you a set of data, how to form an AVL tree. int a[]={4,3,2,7,9,11,10}; 1, insert 4, as shown in figure: the balance factor is 0. 2, insert 3, as shown in figure:, 4 of the balance factor because 4 of the left subtree grew, 1-0=1, 3, insert 2, as the figure, obviously 4 of the balance factor is greater than 1, in order to maintain the balance that we do: let the left child of the 4 node point to the right subtree of 3 (at this time null), let 3 right child point 4, , as shown in figure, this operation we specify for the right-hand operation, this figure is rotated with 4 as the root. The code is as follows

void R_rotate (bitree&t)
{
    bitree p;
    p=t->lchild;    If at this point T points to 4, then p points to 3,
    t->lchild=p->rchild;//3 of the right child rime to 4 of the left sub-tree (this example 3 right subtree is empty)
    p->rchild=t;       Point 3 right child to 4.
    t=p;        Root pointing to Node 3
}

4, insert 7, as shown in figure: 5, insert 9, as shown: Obviously node 4 is unbalanced. Then we put 4 of the right child 7 of the Zuozi (at this time null), let 7 left child point 4, let 3 right child point 7, as shown:, we specify this operation for the left-hand operation, this figure is rotated by the root of 4, the code is as follows:

void L_rotate (bitree&t)
{
    bitree p;
    p=t->rchild;     If at this point T points to 4, then p points to 7.
    t->rchild=p->lchild;  Let 7 of the left child rime to 4 of the right sub-tree
    p->lchild=t;    Let 7 left child point 4
    t=p;   Root point 7
}

6. We insert 11, as shown in figure: obviously 3 nodes, unbalanced, everyone should know to 3 for the root of the left-handed. Let 3 of the right child point to 7 of the Zuozi (this is 4). The left child of 7 points to 3, and the root points to 7, as shown in the following figure:

7. We insert 10, as shown in figure:   Obviously the node 9 is unbalanced and the right side is high, so let's turn left, and the effect after the left is shown in the image on the right. Obviously this is wrong, 10:11 small, but on 11 right child. (The root cause is that the balance factor of 9 and 11 is different) what are we going to do, take a look at the picture:

Success is not far from us, we can easily put this set of data out of the AVL tree, is not very fulfilling. OK, let's summarize the rules of the insertion element.          1, the 3rd step as described above, when inserting an element causes the left side to be high, the right low, and the balance factor symbol of 4 and 3 to be the same, Then right-handed.          2,  as the 5th step above, when inserting node 9, resulting in a tree with 4 as the root of the right high, left low, 4 and 7 the same balance factor symbol, Then the left-hand          3, as described in the 7th step, when inserted node 10, resulting in a tree with 9 roots to the right of the high, left low, Because the balance factor of 9 and 11 is different (that is, the root and his right child's balance factor symbol is different) can not be left-handed, correct operation: you need to right-turn in the left hand, to make Genheggen right child balance factor symbol is the same.          4, 4th rotation and 3 Conversely, when the left is higher than the right, and the root and his left child, the balance factor symbol is different, need to first left and then right-handed, it is so simple. Before implementing the Insert function, we encapsulate 2 functions. Rightbalance (): Call; 
Leftbalance () function when right balance is required: Called when the left balance is required for Zogao; Right balance function code:

void rightbalance (bitree&t) {Bitree r,rl;
    When this function is called, the tree with T is the root, and the right is higher than the left, then T->bf=rh.     r=t->rchild; R is the right child of T switch (R->BF) {case RH://If T's right child and t have their balance factor symbol at the same time, then direct left-handed, this is the 2nd item in the summary t->bf=r-  
        >bf=EH;
        L_rotate (T); break; 
    Case EH:         t->bf=rh;
        r->bf=lh;
        l_rotate (T);
            break;
                          Case LH://If the right child of T and t their balance factor are not the same, it is necessary to first right-hand with T's right child, then t as Root left-handed.    RL for T right child's left child rl=r->lchild; 2 times after rotation, the left child of T's right child is the new root.
        Note: The right child of RL is rime to the left sub-tree of R, and the left child of RL Rime to the right subtree of T switch (RL-&GT;BF)//This switch is the balance factor for the right child to operate T and T after rotation.    {Case eh:t->bf=r->bf=eh;
                           These balance factor operation, we can draw their own understanding of the following note break;
                          2 times after rotation, the left child of T's right child is the new root.
             And the right child of RL is rime to the left sub-tree of R, and the left child of RL is rime to the right subtree of T, and RL is the new root case rh:r->bf=eh;
            t->bf=lh;

        Break
             Case lh:r->bf=rh;
            t->bf=eh;
        Break
        Default:break;    
        } rl->bf=eh;    R_rotate (T->rchild);
        First left-handed, with T->rchild as the root left.  L_rotate (T); Right-handed,The t is the root, the left post T is and RL want to wait, RL is the new root break;
    }} void Leftbalance (bitree&t) {Bitree l,lr;
    l=t->lchild; Switch (L-&GT;BF) {
    Case EH:
l->bf=rh;
t->bf=lh;
R_rotate (T);
break;
    Case LH:
        l->bf=t->bf=eh;
        R_rotate (T);
        break;
    Case RH:
        lr=l->rchild;
        Switch (LR->BF)
        {case
        EH:
            l->bf=l->bf=eh;
        Case RH:
            t->bf=eh;
            l->bf=lh;
            break;
        Case LH:
            l->bf=eh;
            t->bf=rh;
            break;
        Default: Break
            ;
        }
        lr->bf=eh;
        L_rotate (t->lchild);
        R_rotate (T);
        break;
    Default: Break
        ;
    }
}

Haha, two Yuan Reggie we have found, but you see this a little tired, but do not lose heart, success in our feet, now give up, it is not a pity. Then we'll implement the insertion element function.
BOOL Insertavltree (Bitree&t,int Key,bool&taller) {if (!   T)//This tree is empty {t=new bitnode;
        Directly as the root of the whole tree.
        t->bf=eh;
        t->lchild=t->rchild=null;
        t->data=key;
        Taller=true;
    return true;
              } else {if (key==t->data)//existing element, without inserting, returns false; {Taller=false;
           return false; if (key<t->data)//The element is less than the value of this root, look for his left child to go than {if (!
            Insertavltree (T->lchild,key,taller))//The inserted element is less than the value of this root, just look for his left child to go than return false;
            if (taller)//taller is the root, the tree grows taller and is inserted into the left subtree of this root.
                {switch (T-&GT;BF)//Balance factor for this root {case EH://Originally left and right balance, equal height          t->bf=lh;      Left high = "LH taller=true due to insertion into left subtree;"
            Continue to the upper recursion break; Case Lh:leftbalance (T); Originally LH, due to the insertion to the left, this T this tree, imbalance requires left balance taller=falsE
            In order to balance, set taller to false, upward recursion does not have to enter this statement, break;     Case rh:t->bf=eh;
                The original RH, due to the insertion to the left, causes this T-balance to Taller=false;
            Break
            Default:break; }}}} else {if (!
                Insertavltree (T->rchild,key,taller)) return false;
                    if (taller) {switch (T-&GT;BF) {case EH:
                    t->bf=rh;
                    Taller=true;
                Break
                    Case lh:t->bf=eh;
                    Taller=false;
                Break
                    Case Rh:rightbalance (T);
                    Taller=false;
                Break
                Default:break; }
                }
        }
       
         
    }
The middle order traversal output
void Inorderreverse (bitree&t)
{
    if (T)
    {

        inorderreverse (t->lchild);
        cout<<t->data<<endl;
        Inorderreverse (T->rchild);
    }
}
See this, oneself out a set of data or according to the process I just used a set of data into AVL, look at the code to go through, you will have a different receipt of OH (this is very important), and inserted the success, you have succeeded 99%, did not think of yourself so strong, we next completed its deletion operation, we are perfect. If you have a goal to pursue perfection, go with me.
Delete operation of 2.2AVL

Below I will post the code, according to the code to remove the above diagram elements, you will succeed

For better understanding, it is recommended that the insertion code be implemented first.

Delete Code is similar to BST's deletion, and the AVL will take care of the balance after deleting the element.

BOOL Deletelement (Bitree&t,int key,bool&lower)//parameter (0) root, (1) deleted element, (3) Whether this tree lowers the flag bit
{
BOOL l,r;//Deletes the Zuozi or right subtree, as a flag.

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.