An analysis of AVL tree algorithm

Source: Internet
Author: User

AVL Tree Introduction


    avl tree is a highly balanced two-fork tree that adds members to each node of the tree while defining each node of the tree Span style= "font-family: ' The song Body '; > balance factor bf  avl The tree requires that the height difference of the subtree of all nodes does not exceed the BF 2

When we insert a new node, the equilibrium state of the balance tree will be destroyed, so we need to use the corresponding adjustment algorithm to make the tree back to equilibrium.


Pre-knowledge


The previous article said that when inserting new nodes, the structure of the tree might break, so we set up a set of tuning algorithms. Adjustment can be divided into two categories: one is structural adjustment, that is, changing the connection of nodes in the tree, the other is the adjustment of the balance factor, so that the balance factor to meet the requirements of the AVL tree. The adjustment process consists of four basic operations, left rotation , right rotation , right-left double-spin , and left -and double -spin.    

The rotation of the balance tree, with only one purpose, reduces the height of the tree and greatly reduces the complexity of finding the node time in the tree .


L:    

650) this.width=650; "src=" Http://s3.51cto.com/wyfs02/M01/89/7C/wKioL1gVdQnhu5liAACK8B6vgVk373.png "style=" float: none; "title=" 1.png "alt=" Wkiol1gvdqnhu5liaack8b6vgvk373.png "/>

10, 20 is the three nodes of the tree. When a node is inserted in the right subtree of 20, the. When the balance factor of the parent node is the 2,cur node, the balance factor is 1 o'clock left-handed.

The right pointer of the parent points to the left node of the cur, while the left pointer of the CUR points to the parent node. The Cur node inherits the position of the root node of the original parent node in the tree (subtree), and if the original parent node also has a parental node, the cur needs to remain connected to the nodes on the previous layer. (Here we allow the left subtree of the cur to be null)

As you can see, the balance factor of the original parent node and the CUR node becomes 0 after the rotation.



Left rotation code implementation: void Rotatel (node* parent) {node* SUBR = parent->_right;        node* SUBRL = Subr->_left;parent->_right = Subrl;if (SUBRL! = NULL) subrl->_parent = parent; node* Ppnode = Parent->_parent;subr->_left = Parent;parent->_parent = subr;if (PpNode = = NULL) {_root = subR;subR- >_parent = NULL;} Else{if (parent = = ppnode->_left) Ppnode->_left = subr;if (parent = = ppnode->_right) Ppnode->_right = SubR; Subr->_parent = Ppnode;} PARENT->_BF = 0;SUBR->_BF = 0;}


right:650) this.width=650; "Src=" Http://s3.51cto.com/wyfs02/M00/89/7C/wKioL1gVdQnzzHuAAACRy_iOuII509.png " Style= "Float:none;" title= "2.png" alt= "Wkiol1gvdqnzzhuaaacry_iouii509.png"/>

The principle of right-hand and left-handed is similar, and it is mirrored in the relationship. When the balance factor of the parent node becomes the balance factor of the -2,cur node becomes-1, the right-hand rotation occurs.

The left pointer of the parent node points to the right subtree of the CUR node, the right hand of the Cur node, and points to the parent node. At the same time, the CUR node inherits the location of the root nodes of the parent junction in that subtree. That is, if the parent node has its own parents, Cur will keep a pointing relationship with the parent node. (This also allows the right subtree of the cur to be null)

After rotation, you can also find that the balance factor of the parent and CUR nodes becomes 0.

//right rotation code implementation Void rotater (node* parent) {node* subl =  parent->_left; node* sublr = subl->_right;parent->_left = sublr;if  (subLR !=  NULL) {sublr->_parent = parent;} node* ppnode = parent->_parent;subl->_right = parent;     parent->_parent = subl;if  (ppnode == null) {_root = subl;subl->_parent  = null;} else{if  (Parent == ppnode->_left) ppnode->_left = subl;elseppnode->_right  = subl;           subl->_parent =  ppnode;} parent->_bf = 0;subl->_bf = 0;} 

Right-left double-spin:

650) this.width=650; "src=" Http://s2.51cto.com/wyfs02/M02/89/7F/wKiom1gVdo2zJbPRAACsSlIjJ-o900.png "title=" 3.png " alt= "Wkiom1gvdo2zjbpraacsslijj-o900.png"/>

Understanding the situation of Zodan and right paddle, it is simpler to realize the double spin.

Given the case of right-left double-spin, it can be seen that when the balance factor of the parent is 2,cur-1, the right-left double-spin is satisfied.

The realization of right-left double-spin can be divided into three steps.

1> the right rotation with the Parent->_right node as the root.

2> left rotation with parent node as root

3> to adjust.

650) this.width=650; "src=" Http://s2.51cto.com/wyfs02/M01/89/7C/wKioL1gVdtDQYf8BAAJvk2Az5vE749.png "title=" Avl_ Rl.png "alt=" Wkiol1gvdtdqyf8baajvk2az5ve749.png "/>

The first two steps should understand that the problem is not big, but after the right-left rotation, why do you need to adjust it? The reason is that my new node is in the KEY=20 node (cur node left child) Zuozi or right subtree inserted, and maybe 20 is my new node, that is, h=0. The direct result of the three cases is that the balance factor of the left child node of Cur is different. This will be the basis for us to differentiate three situations.

Here's a question to note, in order to improve the reusability of the code, we call the paddle function in the implementation of the double spin, but at the end of paddle, we will have the parent and Cur node's bf set 0. Therefore, we need to preserve the balance factor of the Cur->_left node before paddle. such as

Right left rotation void Rotaterl (node* parent) {node* SUBR = parent->_right; node* SUBRL = subr->_left;size_t BF = subrl->_bf; Rotater (Parent->_right); Rotatel (parent); if (bf = = 0) {PARENT->_BF = 0;SUBR->_BF = 0;SUBRL->_BF = 0;} else if (bf = = 1) {SUBR->_BF = 0;PARENT->_BF = -1;SUBRL->_BF = 0;} ELSE{PARENT->_BF = 0;SUBR->_BF = 1;SUBRL->_BF = 0;}}


Left and right double-spin:


650) this.width=650; "src=" Http://s2.51cto.com/wyfs02/M02/89/7C/wKioL1gVd5PB2PuEAAC8kEkBpLk567.png "title=" 4.png " alt= "Wkiol1gvd5pb2pueaac8kekbplk567.png"/>

The left and right double spins are almost the same, when the balance factor of the parent is 2, and the balance factor of cur is 1 o'clock.

Similar to the concept of right-to-left double-spin, we still have to call the paddle function before adjusting. We also need to pay attention to the influence of the position of the insertion node, and save the balance factor of the right node of cur in advance. This also gives the diagram and code, not too much to repeat.


650) this.width=650; "src=" Http://s4.51cto.com/wyfs02/M00/89/7F/wKiom1gVd9PCmPZTAAJZoomAFfc200.png "title=" Avl_ Lr.png "alt=" Wkiom1gvd9pcmpztaajzoomaffc200.png "/>


Left and right double-spin void ROTATELR (node* parent) {node* Subl = parent->_left; node* SUBLR = subl->_right;size_t BF = sublr->_bf; Rotatel (Parent->_left); Rotater (parent); if (bf = = 0) {PARENT->_BF = 0;SUBL->_BF = 0;SUBLR->_BF = 0;} else if (bf = = 1) {PARENT->_BF = 0;SUBL->_BF = -1;SUBLR->_BF = 0;} ELSE{PARENT->_BF = 1;SUBL->_BF = 0;SUBLR->_BF = 0;}}

Insert algorithm

First we give the definition of the node and the corresponding constructor, in which the _key is the key code and the _value is the value.

Template <typename K, typename v>struct avltreenode{int _BF; K _key; V _value; Avltreenode<k, v>* _left; Avltreenode<k, v>* _right; Avltreenode<k, v>* _parent; Avltreenode (const k& key, const v& value): _BF (0), _key (key), _value (value), _left (null), _right (null), _parent ( NULL) {}};

The next step is to analyze the insertion of the node in several cases:


1. Tree is empty tree (_root = = null)

opens up space and assigns values to the root node and ends directly

if (_root = = NULL) {_root = new Node (k, v); return true;}


2, the tree is not empty tree

To insert a node in a tree, you can roughly divide it into several steps.

1> Find the insertion position of the node.

2> after inserting a node, adjust the point of the node to the parent node.

3> adjusts the balance factor of the insertion node ancestor nodes upward.

because The AVL Tree is a two-fork search tree that, by looping, compares the key value of the node to be inserted and the current node size to find the location of the node to be inserted. At the same time, it opens up space for the node and determines the direction relation of the parent node.

Find the location to insert the node node* cur = _root; node* parent = null;while (cur! = NULL) {parent = Cur;if (k > Cur->_key) {cur = cur->_right;} else if (K < Cur->_key) {cur = cur->_left;} Else{return false;}} Inserts a node, establishes a pointing relationship cur = new node (k, V), if (K < Parent->_key) {Parent->_left = Cur;cur->_parent = parent;} Else{parent->_right = Cur;cur->_parent = parent;}


After inserting the node, the balance factor of the AVL tree node is adjusted. Because of the insertion of a node, the cyclic factor of its ancestor nodes can change, so the loop factor is adjusted upward in a cyclic manner.

It is known that when the node is inserted, the balance factor of all ancestor nodes of the nodal point is not all changing, when the upward adjustment until the balance factor of a node becomes 0, it will no longer adjust upward , because at this point the height of the left and right sub-tree of the node is not changed.

650) this.width=650; "src=" Http://s5.51cto.com/wyfs02/M01/89/7F/wKiom1gVecjyLLsJAABGCQazIpA270.png "title=" 5.png " alt= "Wkiom1gvecjyllsjaabgcqazipa270.png"/>

the next step is to adjust the balance factor upward.

since there is going to be an upward adjustment, here are two pointers defined, theparent pointer and the CUR pointer. After starting the loop, first adjust the balance factor of the parent pointer. After adjustment, judge the balance factor.

The balance factor is 0 , which jumps out of the loop directly.

When the balance factor is 1 or -1 , continue to adjust upward to make the next loop.

When the balance factor is 2 or -2 , use the algorithm we mentioned at the beginning---> the rotation of the balance tree


while (parent) {//adjust parent's bfif (K < Parent->_key) {parent->_bf--;} else{parent->_bf++;} If the parent's Bf is 0, after the surface is inserted into the node, the BF of the heap parent above nodes has no effect if (PARENT->_BF = = 0) {return true;} else if (ABS (PARENT->_BF) = = 1)//for 1,-1 o'clock continue up adjustment {cur = parent;parent = cur->_parent;} ELSE//2, 2 for 2, 2 for rotation adjustment {if (PARENT->_BF = = 2) {if (CUR->_BF = = 1) {Rotatel (parent); else if (CUR->_BF = =-1) {Rotaterl (parent); break;}} ELSE//PARENT->_BF = = -2{if (CUR->_BF = =-1) {rotater (parent); break;} else if (CUR->_BF = = 1) {ROTATELR (parent); break;}}}}


Here, the insertion algorithm is over, and then two functions are given to judge the AVL tree we just built to see if our conditions are met.


bool isbalance () {Int sz = 0;return _isbalance_ Better (_ROOT,&NBSP;SZ);} Bool _isbalance (node* root,int& height) {if  (root == null) return true; int leftheight = 0;if  (_isbalance (root->_left, leftheight)  == false) return false;int rightheight = 0;if  (_isbalance (root->_right, rightheight)  == false) return false;height = leftheight > rightheight ?  Leftheight : rightheight;return abs (leftheight - rightheight)  < 2  &&  (root->_bf == rightheight - leftheight);} 


About the complete AVL tree code, will be given below, here to say a little more is that the AVL tree is a highly balanced two-fork tree, when we build such a binary tree, to find, insert, delete the corresponding node, the efficiency is certainly the highest, time complexity of O (Logn), but in practical applications, Compared to the red and black trees like him, AVL is difficult to achieve and due to the high requirements of the AVL tree (abs (BF) <2) caused by the insertion node to be adjusted several times, the use of the AVL tree is relatively small.


This article is from the "Twilight Back" blog, make sure to keep this source http://muhuizz.blog.51cto.com/11321490/1867315

An analysis of AVL tree algorithm

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.