平衡二叉树
平衡二叉树分为三部分:创建AVL树节点、将结点插入到AVL树中、组装
typedef struct AVLTreeNode{
/* data */
int key; //键值
int height;
struct AVLTreeNode *left; //左孩子
struct AVLTreeNode *right; //右孩子
}Node,*AVLTree;
int Height(AVLTree p){return (p==NULL) ? -1:p->height;}
int MAX(int a,int b){return a>b?a:b;}
void postorder_avltree(AVLTree p){ /*后序遍历AVL树*/}
创建AVL树
创建根节点
/*创建AVL树结点*/
static Node* avltree_creat_node(int key,Node *left,Node *right){
Node* p;
if((p=(Node*)malloc(sizeof(Node)))==NULL) return NULL;//申请空间并判定是否申请成功
p->key=key;//key=key
p->height=0;//高度等于0
p->left=left;
p->right=right;
return p;
}
将结点插入到AVL树中
两点:判断不平衡的条件以及相对应的插入方法
判断条件
/*将结点插入到AVL树中并返回根结点*/
Node* avltree_insert(AVLTree tree, int key){
if(tree==NULL){//只有这段代码是插入的代码
tree=avltree_creat_node(key,NULL,NULL);
if(tree==NULL) return NULL;
}
else if (key<tree->key){
/* code */
tree->left=avltree_insert(tree->left,key);
if(Height(tree->left)-Height(tree->right)==2){//左子树高度减去右子树高度=2
if(key<tree->left->key) tree=LL_Rotation(tree);//左-右=2&&引起失衡的因子比根节点的左子树的值小 LL旋转
else tree=LR_Rotation(tree);//左-右=2&&引起失衡的因子比根节点的左子树的值大 LR旋转
}
}
else if(key>tree->key){
/* code */
tree->right=avltree_insert(tree->right,key);
if(Height(tree->right)-Height(tree->left)==2){//右子树高度减去左子树高度=2
if(key<tree->left->key) tree=RR_Rotation(tree);//右-左=2&&引起失衡的因子比根节点的右子树的值大 RR旋转
else tree=RL_Rotation(tree);//右-左=2&&引起失衡的因子比根节点的右子树的值小 RL旋转
}
}
else{//key=tree.key 添加失败
}
tree->height=MAX(Height(tree->left),Height(tree->right))+1;
return tree;//插入之后返回返回插入的结点本身
}
对应的情况
/*LL:左单旋转。 返回值:旋转后的根节点*/
static Node* LL_Rotation(AVLTree k2){
AVLTree k1;//等于根节点的左子树变为了根节点
k1=k2->left;//选取根节点的左子树为k1
k2->left=k1->right;//k1的右子树变为k2的左子树
k1->right=k2;//k2变为k1的右子树
k2->height=MAX(Height(k2->left),Height(k2->right))+1;//界定k2的高度
k1->height=MAX(Height(k1->left),k2->height)+1;//界定k1的高度
return k1;//返回k1
}
/*RR:右单旋转。 返回值:旋转后的根{节点*/
static Node* RR_Rotation(AVLTree k1){
AVLTree k2;//等于根节点的右子树变为了根节点
k2=k1->right;//选取根节点的左子树为k2
k1->right=k2->left;//k2的左子树变为k1的右子树
k2->left=k1;//k1变为k2的左子树
k1->height=MAX(Height(k2->left),Height(k2->right))+1;//界定k1的高度
k2->height=MAX(Height(k1->left),k2->height)+1;//界定k2的高度
return k2;//返回k2
}
/*LR:左双旋转。 返回值:旋转后的根节点*/
static Node* LR_Rotation(AVLTree k1){
k1->left=RR_Rotation(k1->left);//调整左子树的RR旋转
return LL_Rotation(k1);//调整根节点的LL旋转
}
/*RL:右双旋转。 返回值:旋转后的根节点*/
static Node* RL_Rotation(AVLTree k1){
k1->right=LL_Rotation(k1->right);//调整右子树的LL旋转
return RR_Rotation(k1);//调整根节点的RR旋转
}
组装
void main(){
int arr[]={1,2,5,9,56,78,1};
AVLTree root=NULL;//一个根节点
for(int i=0;i<7;i++){//开始插入
root=avltree_insert(root,arr[i]);
}
postorder_avltree(root);
}
LL顾名思义就是左子树的左边失衡了
RR右子树的右边失衡了
……
在进行LL RR LR RL操作的时候 要将其想象成
截图自这个文章
LL完全体
这个样子