平衡二叉树
特点
- 平衡二叉树是对二叉搜索树的优化,为了防止二叉搜索树退化退化成为链表.通过对树的高度进行如下控制:
- 对于任意一个节点,其左子树和右子树的高度差不能超过1
- 平衡二叉树的高度和节点数量之间的关系是 O(logN)的
- 标记每个节点的高度
定义
template<typename Key, typename Value>
class AVL {
private:
struct Node {
Key key;
Value value;
Node *left;
Node *right;
int height; // 这个节点的所在的高度
Node(key key, Value value) {
this->key = key;
this->value = value;
this->height = 1; // 添加节点的时候,都是添加的叶节点,所以其默认高度为1.
this->left = this->right = NULL;
}
};
Node *root;
int size;
public:
AVL() {
root = NULL;
size = 0;
}
~AVL() {
}
}
常见操作
平衡二叉树的两个重要操作:
- 插入
- 删除
插入和删除类似于 二叉搜索树
. 但是要维护平衡性
帮助函数
-
获得这个节点node的高度
int getHeight(Node* node) { if (node == NULL) // 若为空,返回0 return 0; return node->height; }
-
获得这个节点node的平衡因子
这里使用的左孩子节点的高度 - 右孩子节点的高度
若 >1, 则向左倾斜
若 <-1,则向右倾斜
int getBalanceRFacetor(Node* node) { if (node == NULL) { return 0; } return getHeight(node->left) - getHeight(node->right); }
-
判断这个树是否为
二叉搜索树
BST中序遍历后,判断是否有序.
void inOrder(Node* node, vector<Key> &keys) { if (node) { inOrder(node->left, keys); keys.push_back(node->value); inOrder(node->right, keys); } } bool isBST() { vector<Key> keys; inOrder(root, keys); for (int i = 1; i < keys.size(); i++) { if (keys[i - 1] > keys[i]) return false; } return true; }
-
判断这个数是否为
平衡二叉树
AVL// 判断是否是平衡二叉树 bool isBalanced() { return isBalanced(root); } bool isBalanced(Node* node) { if (node == NULL) return true; int balancedFactor = getBalanceRFacetor(node); if (abs(balancedFactor) > 1) { return false; } // 递归判断其左子树和右子树是否为AVL return isBalanced(node->left) && isBalanced(node->right); }
1. 添加节点
调用方式:
Node* add(Key key, Value value) {
root = add(root, key, value);
return root;
}
节点再怎么失衡都逃不过4种情况:
维护平衡性三个步骤:
- 更新height
- 计算平衡因子
- 调整结构,通过旋转,维护平衡性
- LL (左子树的左边节点)
代码如下:
//右旋转
Node* rightRotate(Node* y) {
Node* x = y->left;
Node* T3 = x->right;
x->right = y;
y->left = T3;
// 更新节点的heigh值
y->height = max(getHeight(y->left),getHeight(y->right))+1;
x->height = max(getHeight(x->left), getHeight(x->right))+1;
return x;
}
- RR (右子树的右边节点)
Node* leftRotate(Node* y) {
Node* x = y->right;
Node* T2 = x->left;
x->left = y;
y->right = T2;
// 更新节点的heigh值
y->height = max(getHeight(y->left), getHeight(y->right)) + 1;
x->height = max(getHeight(x->left), getHeight(x->right)) + 1;
return x;
}
- LR情况(左子树的右边节点)
// LR,
if (balanceFactor > 1 && getBalanceRFacetor(node->left) < 0) {
node->left = leftRotate(node->left);
return rightRotate(node);
}
- 右左情况(右子树的左边节点)
// RL
if (balanceFactor < -1 && getBalanceRFacetor(node->right) > 0) {
node->right = rightRotate(node->right);
return leftRotate(node);
}
完整代码:
Node* add(Node* node, Key key, Value value) {
if (node == NULL) {
node = new Node(key,value);
size++;
return node;
}
if (key < node->key) {
node->left = add(node->left, key, value);
} else if (key > node->value) {
node->right = add(node->right, key, value);
} else {
node->value = value;
}
// 更新height
node->height = 1 + max(getHeight(node->left), getHeight(node->right));
// 计算平衡因子
int balanceFactor = getBalanceRFacetor(node);
// 维护平衡性
if (abs(balanceFactor) > 1) {
// LL 1. 插入的元素在不平衡节点的左侧的左侧,右旋转(向左偏斜)
if (balanceFactor > 1 && getBalanceRFacetor(node->left)>=0) {
return rightRotate(node);
}
// RR 2. 插入的元素在不平衡节点的右侧的右侧,左旋转(向右偏斜)
if (balanceFactor < -1 && getBalanceRFacetor(node->right) <= 0) {
return leftRotate(node);
}
// LR,
if (balanceFactor > 1 && getBalanceRFacetor(node->left) < 0) {
node->left = leftRotate(node->left);
return rightRotate(node);
}
// RL
if (balanceFactor < -1 && getBalanceRFacetor(node->right) > 0) {
node->right = rightRotate(node->right);
return leftRotate(node);
}
}
return node;
}
2.删除节点
删除节点时,需要对删除后的节点进行 平衡性维护
,
所以要设置一个返回用的节点,记作 retNode
.
调用方法:
Node* remove(Key key) {
return remove(root, key);
}
Node* remove(Node* node, Key key) {
if (node == NULL)
return NULL;
// 需要对删除后的节点进行 平衡性维护
// 所以要设置一个返回用的节点, 记作 retNode .
Node* retNode;
if (key < node->key) {
node->left = remove(node->left, key);
retNode = node;
}
else if (key > node->key) {
node->right = remove(node->right, key);
retNode = node;
}
else { // 当前要删除的节点
// 待删除节点左子树为空
if (node->left == NULL) {
Node* rightNode = node->right;
node->right = NULL;
size--;
retNode = rightNode;
}
else if (node->right == NULL) {
Node* leftNode = node->left;
node->left = NULL;
size--;
retNode = leftNode;
}
else {
// 左右子树都不为空
Node* successor = minmum(node->right);
// removeMin中没有进行平衡维护
// successor->right = removeMin(node->right);
successor->right = move(node->right, successor->key);
successor->left = node->left;
node->left = node->right = NULL;
retNode = successor;
}
}
if (retNode == NULL) {
return NULL;
}
// 更新height
retNode->height = 1 + max(getHeight(retNode->left), getHeight(retNode->right));
// 计算平衡因子
int balanceFactor = getBalanceRFacetor(retNode);
// 维护平衡性
if (abs(balanceFactor) > 1) {
// LL 右旋转(向左偏斜)
if (balanceFactor > 1 && getBalanceRFacetor(retNode->left) >= 0) {
return rightRotate(retNode);
}
// RR 左旋转(向右偏斜)
if (balanceFactor < -1 && getBalanceRFacetor(retNode->right) <= 0) {
return leftRotate(retNode);
}
// LR,
if (balanceFactor > 1 && getBalanceRFacetor(retNode->left) < 0) {
retNode->left = leftRotate(retNode->left);
return rightRotate(retNode);
}
// RL
if (balanceFactor < -1 && getBalanceRFacetor(retNode->right) > 0) {
retNode->right = rightRotate(retNode->right);
return leftRotate(retNode);
}
}
return retNode;
}