AVL平衡二叉树的插入与删除

什么是平衡二叉树

首先我们需要知道什么是平衡二叉树:
	平衡二叉树又称为AVL树,它具有以下的性质:
	1.它是一颗空树或它的左右两个子树的高度差绝对值不超过1;
	2.左右子数都是一颗平衡二叉树;
	
我们今天的增加与删除是在二叉搜索树的情况下进行
那么什么是二叉搜索树呢?
	若二叉搜索树的左子树不空,则左子树上的所有节点的值均小于它的根节点的值;
若它的右子树不空,则右子树上所有节点的值均大于它的根节点的值;它的左右两边也为二
叉搜索树。

旋转

	在遇到平衡二叉树的增加与删除时,如果插入与删除后破坏了二叉树的平衡性,
则需要进行旋转。
下面我们分别讨论旋转的四种情况:
1.左旋(ll_rotation)
相关代码
 60 static AVLNode* ll_rotation(AVLTree k2){
 61     AVLNode *k1=k2->left;
 62     k2->left=k1->right;
 63     k1->right=k2;
 64    
 65     return k1;
 66 }
 	k2为根节点

AVL平衡二叉树的插入与删除_第1张图片

2.右旋(rr_rotation)
相关代码:
70 static AVLNode* rr_rotation(AVLTree k1){
 71     AVLNode *k2=k1->right;
 72     k1->right = k2->left;
 73     k2->left = k1;
 74 
 75     return k2;
 76 }
	k1为根节点

AVL平衡二叉树的插入与删除_第2张图片

3.先右旋在左旋(lr_rotation)
相关代码:
 79 static AVLNode* lr_rotation(AVLTree k3){
 80     k3->left = rr_rotation(k3->left);
 81     return ll_rotation(k3);
 82 }
 	k3为根节点

AVL平衡二叉树的插入与删除_第3张图片

4.先左旋再右旋(rl_rotation)
相关代码
 84 static AVLNode* rl_rotation(AVLTree k1){
 85     k1->right = ll_rotation(k1->right);
 86     return rr_rotation(k1);
 87 }

AVL平衡二叉树的插入与删除_第4张图片

平衡二叉树插入

 52 static AVLNode* create_avlnode(int key){
 53     AVLNode *node = malloc(sizeof(AVLNode));
 54     node->key=key;
 55     node->left=NULL;
 56     node->right = NULL;
 57     node->height = 1;
 58     return node;
 59 }//创建新的节点

 89 int avltree_insert(AVLTree *ptree,int key){
 90     if(*ptree == NULL){
 91         *ptree = create_avlnode(key);
 92         return 0;//创建成功
 93     }
 94     int ret = 0;
 95     if(key<(*ptree)->key){//左插,ll 或 lr旋转
 96         ret = avltree_insert(&(*ptree)->left,key);//判断插入的成功与失败
 97         if(ret == 0){//只有插成功
 98             if(HEIGHT((*ptree)->left)-HEIGHT((*ptree)->right) == 2){//在左边插入时失衡,一定是左子树的高度减去右子树的高度
 		等于2时才是失衡,如果没有等于二就不用进行后面的操作
 99                 int lh = HEIGHT((*ptree)->left->left);//删除节点左子树的左侧高度
100                 int rh = HEIGHT((*ptree)->left->right);//删除节点左子树的右侧高度
101                 if(lh>rh){//左子树的左侧高则大于右侧高度则ll旋转,否则lr旋转
102                     *ptree = ll_rotation(*ptree);
103                 }else{
104                     *ptree = lr_rotation(*ptree);
105                 }
106             }//其他情况下说明<=1,不用做调整,还是平衡
107             (*ptree)->height = MAX(HEIGHT((*ptree)->left),HEIGHT((*ptree)->right))    +1;//更新插入后的高度,加的一为自己
		本身的高度为1
108         }
109         return ret; //递归时返回成功还是失败
110     }else if(key>(*ptree)->key){//删除的值在右子树的情况,与上面同理
111         ret = avltree_insert(&(*ptree)->right,key);
112         if(ret == 0){
113             if(HEIGHT((*ptree)->right)-HEIGHT((*ptree)->left) == 2){
114                 int lh = HEIGHT((*ptree)->right->left);
115                 int rh = HEIGHT((*ptree)->right->right);
116                 if(rh>lh){
117                     *ptree = rr_rotation(*ptree);
118                 }else{
119                     *ptree = rl_rotation(*ptree);
120                 }
121             }
122             (*ptree)->height = MAX(HEIGHT((*ptree)->left),HEIGHT((*ptree)->right))+1;
123         }
124         return ret;
125     }else{//有相同的元素
126         return -1;
127     }
128 }

平衡二叉树删除

177 int avltree_delete(AVLTree *ptree,int key){
178     if(*ptree == NULL){ //如果要删除的节点不存在,就返回-1
179         return -1;
180     }
181     int ret = 0;
182     if((*ptree)->key == key){   //如果找到了要删除的节点
183         AVLNode *node = *ptree;     //记录要删除的节点*ptree
184         if(node->right && node->left){  //如果要被删除的节点的左右节点都存在
185             int hl = HEIGHT(node->left);    //被删除节点左儿子的高度
186             int hr = HEIGHT(node->right);   //被删除节点的右儿子的高度
187             if(hl > hr){//左边高,左边的最大值放到node里面,把最大值的节点删除
188                 AVLNode* max = node->left;  //用来储存左儿子的最右的节点
189                 while(max->right){          //找到最右的节点
190                     max = max->right;
191                 }
192                 node->key = max->key;       //把这个最大值节点覆盖要被删除的节点
193                 ret = avltree_delete(&(node->left),max->key);   //删除左儿子这个树
    里的最大值
194                 (*ptree)->height = MAX(HEIGHT((*ptree)->left),HEIGHT((*ptree)->rig    ht)) + 1; //更新该被
			删除(其实删除的不是他,是左儿子的最大值的几诶单)的节点的高度
195             }else{  //右边高    右边的最小值放到node里面,然后把这个最小值删除
196                 AVLNode *min = node->right; //记录右儿子的最左节点
197                 while(min->left){           //找到右儿子的最左节点
198                     min = min->left;
199                 }
200                 node->key = min->key;       //用这个最左节点覆盖要被删除的节点
201                 ret = avltree_delete(&(node->right),min->key);  //删除右儿子这个树
    里的最小值
202                 (*ptree)->height = MAX(HEIGHT((*ptree)->left),HEIGHT((*ptree)->rig    ht)) + 1;//更新这个
(要被删除)(其实删除的不是他,是右儿子的最小值)的节点的高度
203             }
204         }else if(!node->right && !node->left){  //如果要被删除的节点的左右儿子都不
    存在,那么直接删除该节点
205             free(*ptree);
206             *ptree = NULL;
207         }else{  //如果要被删除的节点的左右儿子只存在其中一个  直接把左儿子或者右儿
    子提上来,并且释放掉此节点
208             AVLNode *node = *ptree;
209             *ptree = (*ptree)->left!=NULL?(*ptree)->left:(*ptree)->right;
210             free(node);
211         }
212         return 0;
213     }else if(key < (*ptree)->key){  //如果要被删除的节点在左边
214         ret = avltree_delete(&(*ptree)->left,key);  //那就去左边删除此节点
215         if(ret == 0){   //如果删除成功 那就判断此树是否还平衡   左边被删除掉一个结
    点,肯定是右边变高
216             if(HEIGHT((*ptree)->right)-HEIGHT((*ptree)->left) == 2){    //如果不平
    衡则需要rr旋转或者rl旋转
217                 int hl = HEIGHT((*ptree)->right->left); //  右儿子这棵树的左边的高218                 int hr = HEIGHT((*ptree)->right->right);    //右儿子这棵树的右边的
    高度
219                 if(hl>hr){      //如果左边高
220                     *ptree = rl_rotation(*ptree);   //那就需要rl旋转
221                 }else{      //如果右边高
222                     *ptree = rr_rotation(*ptree);   //那就需要rr旋转
223                 }
224             }
225             (*ptree)->height = MAX(HEIGHT((*ptree)->left),HEIGHT((*ptree)->right))    +1;   //更新这个节点的高度
226         }
227         return ret; //返回删除结果
228     }else{  //要被删除的节点在右边
229         ret = avltree_delete(&(*ptree)->right,key);
230         if(ret == 0){
231             if(HEIGHT((*ptree)->left)-HEIGHT((*ptree)->right) == 2){
232                 int hl = HEIGHT((*ptree)->left->left);
233                 int hr = HEIGHT((*ptree)->left->right);
234                 if(hl>hr){
235                     *ptree = ll_rotation(*ptree);
236                 }else{
237                     *ptree = lr_rotation(*ptree);
238                 }
239             }
240             (*ptree)->height = MAX(HEIGHT((*ptree)->left),HEIGHT((*ptree)->right))    +1;
241         }
242         return ret;
243     }
244 }



你可能感兴趣的:(C语言,嵌入式,AVL平衡二叉树)