平衡二叉树

一、概念:平衡二叉树是一种高度平衡的二叉排序树,其中每一个结点的左子树和右子树的高度差的绝对值至多为1.

    平衡因子(BF):BF=左子树高度-右子树高度

     最小不平衡子树:距离插入结点最近,且平衡因子的绝对值大于1的结点的根的子树称为最小不平衡子树

二:平衡二叉树的实现原理:
  

下面是失衡的四种情况(图片摘自王卓的课程)

失衡的调整:

1)LL型

对于LL型失衡需要通过对根结点A进行右旋调整:

  • 将 左子节点(B) 提升为新的根节点。
  • 原根节点(A)成为 B 的右子节点
  • Y 的原右子树(β)转移到 A 的左子树(保持二叉搜索树的顺序) 

调整后: 

 2)RR型

对于RR型失衡需要通过对根结点A进行左旋调整:

  • 将  右子节点(B) 提升为新的根节点。
  • 原根节点(A)成为 B 的左子节点
  • B 的原左子树(α)转移到 A 的右子树(保持二叉搜索树的顺序)

调整后:

 3)LR型:需要对其左子树进行左旋使其变成LL型,然后再进行右旋。

4)RL型:需要对其右子树进行右旋使其变成RR型,然后再进行左旋。

三、算法实现:

构建平衡二叉树的基本思想:在构建二叉排序树的过程中,每插入一个结点,先检查是否因插入而破坏了树的平衡性,若是,则找出最小不平衡树,对其进行调整,使其成为新的平衡子树。

首先是树结点结构:

struct TNode{
	int BF;        //增加一个平衡因子 
	int val;
	TNode* lc;
	TNode* rc; 
	TNode(int v):val(v),lc(NULL),rc(NULL),BF(0){}  
}; 

接着是左旋和右旋的函数:

void R_Rotate(TNode* &root){  //右旋函数 
	TNode* x=root->lc;
	TNode* y=x->rc;	
	x->rc=root; 
	root->lc=y;
	root=x;    //根结点指向x。 
}
void L_Rotate(TNode* &root){   //左旋函数(与右旋相反) 
	TNode* x=root->rc;
	TNode* y=x->lc;
	x->lc=root;
	root->rc=y;
	root=x;
}

然后是处理最小不平衡子树的函数:

这个函数的关键是处理后相关结点的BF的计算,也是最难的一个点。

void LeftBalance(TNode* &root){   //调整左树过高 ,这个函数的关键是BF值的修改 
	TNode* x=root->lc;
	TNode* y=x->rc;
	if(x->BF==1){     //LL型
		root->BF=0;
		x->BF=0;           //LL型调整过后root和x的BF都为0 
		R_Rotate(root);
	} 
	else{          //这里x的BF为-1  (LR型)
		switch(y->BF){  
			case 1:
                root->BF = -1;
                x->BF = 0;
                break;
            case 0:
                root->BF =0;
				 x->BF = 0;
                break;
            case -1:
                root->BF = 0;
                x->BF = 1;
                break; 
		} 
		y->BF = 0;
        L_Rotate(root->lc);
        R_Rotate(root);
          
	}
}
 
void RightBalance(TNode* &root){    //和LeftBalance函数类似 
	TNode* x=root->rc;
	TNode* y=x->lc;
	if(x->BF==-1){
		root->BF=0;
		x->BF=0;
		L_Rotate(root);
	}
	else{
		switch(y->BF){
			case 1:
				root->BF=0;
				x->BF=-1;
				break;
			case 0:
				root->BF=0;
				x->BF=0;
				break;
			case -1:
				root->BF=1;
				x->BF=0;
				break;
				
		}
		y->BF=0;
		R_Rotate(root->rc);
		L_Rotate(root);
	}	
} 

最后是插入函数:

插入函数在插入的同时需要判断其是否长高,如果长高就要判断其是否失衡,若失衡则要调用处理最小不平衡子树的函数来调整。

bool Insert_AVL(TNode* &root,int value,bool &higher){   //插入并构建平衡二叉树    higher:用来判断插入操作是否使树高度增加 
	 if(!root){
	 	root=new TNode(value);
	 	higher=true;
	 	return true;
	 }     
	else if(root->val==value)
	    return false;
	else{
		bool inserted=false;
		if(value<root->val){
			inserted=Insert_AVL(root->lc,value,higher);
			if(inserted){
				if(higher){
					switch(root->BF){
						case 1:                
							LeftBalance(root);   //进行平衡调整过后higher变为false 
							higher=false;						
							break;
						case 0:              
							root->BF=1;     
							higher=true;     //左树长高,整体长高 
							break;
						case -1:
							root->BF=0;     //原先右树高于左树,整体高度不变 
							higher=false;
							break;
					}
				}
				return true;
			}
		    return false;
		}
		else{
			inserted=Insert_AVL(root->rc,value,higher);
			if(inserted){
				if(higher){
					switch(root->BF){
						case 1:
							root->BF=0;
							higher=false;
							break;
						case 0:
							root->BF=-1;
							higher=true;
							break;
						case -1:
							RightBalance(root);
							higher=false;
							break;
					}
				}
				return true;
			}
			return false;
		}
	}
} 

整体代码:

#include<iostream>
using namespace std;
struct TNode{
	int BF;        //增加一个平衡因子 
	int val;
	TNode* lc;
	TNode* rc; 
	TNode(int v):val(v),lc(NULL),rc(NULL),BF(0){}  
}; 
void R_Rotate(TNode* &root){  //右旋函数 
	TNode* x=root->lc;
	TNode* y=x->rc;	
	x->rc=root; 
	root->lc=y;
	root=x;    //根结点指向x。 
}
void L_Rotate(TNode* &root){   //左旋函数(与右旋相反) 
	TNode* x=root->rc;
	TNode* y=x->lc;
	x->lc=root;
	root->rc=y;
	root=x;
}
void LeftBalance(TNode* &root){   //调整左树过高 ,这个函数的关键是BF值的修改 
	TNode* x=root->lc;
	TNode* y=x->rc;
	if(x->BF==1){
		root->BF=0;
		x->BF=0;           //LL型调整过后root和x的BF都为0 
		R_Rotate(root);
	} 
	else{          //这里x的BF为-1 
		switch(y->BF){
			case 1:
                root->BF = -1;
                x->BF = 0;
                break;
            case 0:
                root->BF =0;
				 x->BF = 0;
                break;
            case -1:
                root->BF = 0;
                x->BF = 1;
                break; 
		} 
		y->BF = 0;
        L_Rotate(root->lc);
        R_Rotate(root);
          
	}
}
 
void RightBalance(TNode* &root){    //和LeftBalance函数类似 
	TNode* x=root->rc;
	TNode* y=x->lc;
	if(x->BF==-1){
		root->BF=0;
		x->BF=0;
		L_Rotate(root);
	}
	else{
		switch(y->BF){
			case 1:
				root->BF=0;
				x->BF=-1;
				break;
			case 0:
				root->BF=0;
				x->BF=0;
				break;
			case -1:
				root->BF=1;
				x->BF=0;
				break;
				
		}
		y->BF=0;
		R_Rotate(root->rc);
		L_Rotate(root);
	}	
} 
bool Insert_AVL(TNode* &root,int value,bool &higher){   //插入并构建平衡二叉树    higher:用来判断插入操作是否使树高度增加 
	 if(!root){
	 	root=new TNode(value);
	 	higher=true;
	 	return true;
	 }     
	else if(root->val==value)
	    return false;
	else{
		bool inserted=false;
		if(value<root->val){
			inserted=Insert_AVL(root->lc,value,higher);
			if(inserted){
				if(higher){
					switch(root->BF){
						case 1:                
							LeftBalance(root);   //进行平衡调整过后higher变为false 
							higher=false;						
							break;
						case 0:              
							root->BF=1;     
							higher=true;     //左树长高,整体长高 
							break;
						case -1:
							root->BF=0;     //原先右树高于左树,整体高度不变 
							higher=false;
							break;
					}
				}
				return true;
			}
		    return false;
		}
		else{
			inserted=Insert_AVL(root->rc,value,higher);
			if(inserted){
				if(higher){
					switch(root->BF){
						case 1:
							root->BF=0;
							higher=false;
							break;
						case 0:
							root->BF=-1;
							higher=true;
							break;
						case -1:
							RightBalance(root);
							higher=false;
							break;
					}
				}
				return true;
			}
			return false;
		}
	}
} 
void preOrder(TNode* root){   //前序遍历 
	if(!root)
	    return;
	else{
		cout<<root->val<<" ";
		preOrder(root->lc);
		preOrder(root->rc);
	}
}
// 释放内存
void DestroyTree(TNode* root) {
    if(root) {
        DestroyTree(root->lc);
        DestroyTree(root->rc);
        delete root;
    }
}
int main(){
	int value;
	int n,i;
	TNode* root=NULL;
	bool higher=false;
	cin>>n;
	for(i=0;i<n;i++){
		cin>>value;
		Insert_AVL(root,value,higher);
		
	}
	preOrder(root); 
	DestroyTree(root);
	return 0;
} 

运行结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值