avltree, 平衡二叉查找树,是一种特殊情况下的二叉查找树,它的特殊之处在于,对于每一个节点,其左子树深度和右子树深度之差的绝对值不大于1.
自从上次写完BSTree后,心里想写AVL树了,查了点资料,感觉自己之前的结构是真的low,哎,知耻而后勇,先说一下这次的avl与上次bstree的两点不同:
1)节点数据结构中新增了一个高度变量,代码如下:
struct Node{
struct Node *left;
struct Node *right;
int val;
int height;
Node(int x):val(x), height(1), left(NULL), right(NULL){}
};
2)逻辑上,该树的根节点,多了一个父节点,该父节点没有实际意义,只是为了方便后续的所有关于该树的增删改查(别想到数据库。。。)的操作。形式如下图:
之后就要开启我们的插入和删除操作了,为什么没有查找?由于avl是一种bst,所以查找操作不在此赘述。
更多C/C++Linux视频资料请加qun:832218493或vx关注零声学院免费领取!
插入时,由于要保证平衡这一性质,所以要针对不同不平衡情况进行分别处理,其中,不平衡的情况分为左左失衡,右右失衡,左右失衡,右左失衡,下面进行分情况讨论处理,这里有一点需要说明的是,以上四种情况都要找到,发生不平衡的最低的树节点。
左左失衡:情况如图:
调整后的结果如下图:
struct Node *avltree::ll_rotate(struct Node *y){
struct Node *x = y->left;
y->left = x->right;
x->right = y;
y->height = std::max(getHeight(y->left), getHeight(y->right)) +1;
x->height = std::max(getHeight(x->left), getHeight(x->right)) +1;
return x;}
右右失衡情况如下图:
调整后如下图:
代码奉上:
struct Node *avltree::rr_rotate(struct Node *y){
struct Node *x = y->right;
y->right = x->left;
x->left = y;
y->height = std::max(getHeight(y->left), getHeight(y->right)) +1;
x->height = std::max(getHeight(x->left), getHeight(x->right)) +1;
return x;
}
左右失衡如下图,这种情况需要先将x按照右右失衡情况处理,转换为左左失衡,然后按照左左失衡处理:
第一步处理完后,如下图:
之后就按照左左失衡处理就行了,代码奉上:
struct Node *avltree::lr_rotate(struct Node *y){
struct Node *x = y->left;
y->left = rr_rotate(x);
return ll_rotate(y);
}
第一步调整后的结果如下图:
之后就按照右右失衡处理就行了,代码奉上:
struct Node *avltree::rl_rotate(struct Node *y){
struct Node *x = y->right;
y->right = ll_rotate(x);
return rr_rotate(y);
}
接下来奉上整个插入代码:
struct Node *avltree::insert(int k, struct Node *node){
if(node == NULL) return (new struct Node(k));
if(k < node->val) node->left=insert(k, node->left);
else if( k > node->val) node->right=insert(k, node->right);
else return node;
node->height = std::max(getHeight(node->right), getHeight(node->left)) + 1;
int balance = isBalance(node);
if(balance > 1 && isBalance(node->left)>0) return ll_rotate(node);
if(balance > 1 && isBalance(node->left)<0) return lr_rotate(node);
if(balance < -1 && isBalance(node->right) > 0) return rl_rotate(node);
if(balance < -1 && isBalance(node->right) < 0) return rr_rotate(node);
return node;
}
void avltree::insert(int k){
root->left = insert(k, root->left);
}
删除的话,跟插入是非常类似的,直接上代码了~:
struct Node *avltree::delNode(int k, struct Node *node){
if(node==NULL) return NULL;
if(k < node->val) node->left = delNode(k, node->left);
else if(k > node->val) node->right = delNode(k, node->right);
else{
if(node->left && node->right){
struct Node *x = node->right;
while(x->left) x = x->left;
node->val = x->val;
node->right = delNode(x->val, node->right);
}else{
struct Node *p = node;
node = node->left?node->left:node->right;
delete p, p = NULL;
if(node == NULL) return NULL;
}
}
node->height = std::max(getHeight(node->right), getHeight(node->left)) + 1;
int balance = isBalance(node);
if(balance > 1 && isBalance(node->left)>0) return ll_rotate(node);
if(balance > 1 && isBalance(node->left)<0) return lr_rotate(node);
if(balance < -1 && isBalance(node->right) > 0) return rl_rotate(node);
if(balance < -1 && isBalance(node->right) < 0) return rr_rotate(node);
return node;
}
void avltree::delNode(int k){
root->left = delNode(k, root->left);
}
整个类的代码如下:
#ifndef AVLTREE_H
#define AVLTREE_H
#include <iostream>
struct Node{
struct Node *left;
struct Node *right;
int val;
int height;
Node(int x):val(x), height(1), left(NULL), right(NULL){}
};
class avltree
{
public:
avltree();
int isBalance(struct Node *node);
int getHeight(struct Node *node);
struct Node *ll_rotate(struct Node *y);
struct Node *rr_rotate(struct Node *y);
struct Node *lr_rotate(struct Node *y);
struct Node *rl_rotate(struct Node *y);
struct Node *insert(int k, struct Node *node);
void insert(int k);
struct Node *delNode(int k, struct Node *node);
void delNode(int k);
struct Node *root;
};
#endif // AVLTREE_H
avltree::avltree(){
root = new struct Node(0);
}
int avltree::isBalance(struct Node *node){
if(node == NULL) return 0;
return getHeight(node->left) - getHeight(node->right);
}
int avltree::getHeight(struct Node *node){
if(node == NULL) return 0;
return node->height;
}
struct Node *avltree::ll_rotate(struct Node *y){
struct Node *x = y->left;
y->left = x->right;
x->right = y;
y->height = std::max(getHeight(y->left), getHeight(y->right)) +1;
x->height = std::max(getHeight(x->left), getHeight(x->right)) +1;
return x;
}
struct Node *avltree::rr_rotate(struct Node *y){
struct Node *x = y->right;
y->right = x->left;
x->left = y;
y->height = std::max(getHeight(y->left), getHeight(y->right)) +1;
x->height = std::max(getHeight(x->left), getHeight(x->right)) +1;
return x;
}
struct Node *avltree::lr_rotate(struct Node *y){
struct Node *x = y->left;
y->left = rr_rotate(x);
return ll_rotate(y);
}
struct Node *avltree::rl_rotate(struct Node *y){
struct Node *x = y->right;
y->right = ll_rotate(x);
return rr_rotate(y);
}
struct Node *avltree::insert(int k, struct Node *node){
if(node == NULL) return (new struct Node(k));
if(k < node->val) node->left=insert(k, node->left);
else if( k > node->val) node->right=insert(k, node->right);
else return node;
node->height = std::max(getHeight(node->right), getHeight(node->left)) + 1;
int balance = isBalance(node);
if(balance > 1 && isBalance(node->left)>0) return ll_rotate(node);
if(balance > 1 && isBalance(node->left)<0) return lr_rotate(node);
if(balance < -1 && isBalance(node->right) > 0) return rl_rotate(node);
if(balance < -1 && isBalance(node->right) < 0) return rr_rotate(node);
return node;
}
void avltree::insert(int k){
root->left = insert(k, root->left);
}
struct Node *avltree::delNode(int k, struct Node *node){
if(node==NULL) return NULL;
if(k < node->val) node->left = delNode(k, node->left);
else if(k > node->val) node->right = delNode(k, node->right);
else{
if(node->left && node->right){
struct Node *x = node->right;
while(x->left) x = x->left;
node->val = x->val;
node->right = delNode(x->val, node->right);
}else{
struct Node *p = node;
node = node->left?node->left:node->right;
delete p, p = NULL;
if(node == NULL) return NULL;
}
}
node->height = std::max(getHeight(node->right), getHeight(node->left)) + 1;
int balance = isBalance(node);
if(balance > 1 && isBalance(node->left)>0) return ll_rotate(node);
if(balance > 1 && isBalance(node->left)<0) return lr_rotate(node);
if(balance < -1 && isBalance(node->right) > 0) return rl_rotate(node);
if(balance < -1 && isBalance(node->right) < 0) return rr_rotate(node);
return node;
}
void avltree::delNode(int k){
root->left = delNode(k, root->left);
}
如果各位看官发现有问题,欢迎留言探讨~