①定义
平衡二叉树:对于二叉树中任意节点,左子树的高度和右子树的高度差的绝对值不超过1.还有一点,平衡二叉树是一种位置高度平衡的二叉搜索树。二叉搜索树详见上一篇博客。
②平衡二叉树的四种旋转
平衡二叉树的创建在于对于插入节点后,需要对插入之后的树进行维护高度。
维护高度的方法有四种:左旋,右旋,左右旋,右左旋。
树的结构
typedef struct Node *node;
struct Node{
node left;
node right;
int data;
};
四种维护高度的方法代码:分别对应的代码如下
void left(node root){ //左旋,返回的是对于root左旋后的新的根节点
node tmp = root->left;
root->left = tmp->right;
tmp->right = root;
return tmp;
}
void right(node root){//同理,右旋
node tmp = root->left;
root->right = tmp->left;
tmp ->left = root;
return tmp;
}
node left_right(node root){ //左右选,可以理解为先对左孩子进行右旋矫正之后在进行根节点左旋
root->left = right(root->left);
return left(root);
}
node right_left(node root){//同理,右左旋
root->right = left(root->right);
return right(root);
}
在了解四种维护高度的代码之后,具体原因以及旋转机制,详见自己课本(嘿嘿!)
③节点的插入
对于AVL树的插入,与二叉搜索树的插入原理相同,只是多了维护高度的步骤,代码如下:
int get_high(node root){ //简单的遍历二叉树进行获取节点root的高度
if(root == NULL)
return 1;
else
return max(get_high(root->left), get_high(root->right)) + 1;
}
node Insert(node root,int x){
if(!root){
node tmp = (node)malloc(sizeof(struct Node));
tmp->left = NULL;
tmp->right = NULL;
tmp ->data= x;
root = tmp;
}else if(x > root->data){
root->right = Insert(root->right, x);
if(get_high(root->left) - get_high(root->right) == -2)
{//若等于 -2,说明插入右子树的节点导致二叉树不平衡
if(x > root->right->data){ //如果是插入右孩子的右边导致不平衡,则直接右旋
root = right(root);
}else if(x < root->right->data){//反之,则是插入右孩子的左孩子导致不平衡
root = right_left(root);//直接右左旋
}
}
}else if(x < root->data){ //同上 右子树的高度维护
root->left = Insert(root->left, x);
if(get_high(root->left) - get_high(root->right) == 2){
if(x > root->left->data){
root = left_right(root);
}else if(x < root->left->data){
root = left(root);
}
}
}
return root;
}