AVL树
AVL 树是一种平衡二叉树,得名于其发明者的名字( Adelson-Velskii 以及 Landis)。
平衡二叉树递归定义如下:
-
什么是二叉搜索树
任一结点 小于 其左子树的所有结点小于 其右子树的所有结点;
结点的左右子树,也是二叉排序树;
-
什么是AVL树
搜索二叉树的每个结点的左、右子树高度之差的绝对值不超过1.
同时引入平衡因子的概念,即:结点的平衡因子= 右子树高度 – 左子树高度
AVL树节点定义
节点包括:
AVLTreeNode | Type |
---|---|
val(节点值) | int |
bf(平衡因子) | int |
leftTree(左子树) | AVLTreeNode* |
leftTree(右子树) | AVLTreeNode* |
定义如下:
struct AVLTreeNode
{
int val; // 节点值
int bf; // 平衡因子
AVLTreeNode* leftTree; // 左子树
AVLTreeNode* rightTree; // 右子树
AVLTreeNode() :val(0), bf(0), leftTree(NULL), rightTree(NULL) {}
AVLTreeNode(int valable) :val(valable), bf(0), leftTree(NULL), rightTree(NULL) {}
AVLTreeNode(int valable, int be, AVLTreeNode* lf, AVLTreeNode* rf) :val(valable), bf(be), leftTree(lf), rightTree(rf) {}
AVLTreeNode* setAVLTree(vector<int> nums); // 插入平衡算法
};
平衡方式
LL形
- 不平衡原因:新结点插入到A的左子女的左子树中导致不平衡
算法:
void rotateLL(AVLTreeNode*& root) {
AVLTreeNode* currL = root;
root = currL->rightTree;
currL->rightTree = root->leftTree;
root->leftTree = currL;
root->bf = currL->bf = 0;
}
图示:
RR形
- 不平衡原因:新结点插入到A的右子女的右子树中导致不平衡
算法示例:
void rotateRR(AVLTreeNode*& root) {
AVLTreeNode* curr = root;
root = curr->leftTree;
curr->leftTree = root->rightTree;
root->rightTree = curr;
root->bf = curr->bf = 0;
}
图示过程:
LR形
- 不平衡原因:新结点插入到A的左子女的右子树中导致不平衡
算法示例:
void rotateLR(AVLTreeNode*& root) {
AVLTreeNode* currL = root->leftTree;
AVLTreeNode* currR = root;
root = currL->rightTree;
currL->rightTree = root->leftTree;
root->leftTree = currL;
if (root->bf <= 0)currL->bf = 0;
else
currL->bf = -1;
currR->leftTree = root->rightTree;
root->rightTree = currR;
if (root->bf == -1)
currR->bf = 1;
else
currR->bf = 0;
root->bf = 0;
}
图示过程:
RL形
- 不平衡原因:新结点插入到A的右子女的左子树中导致不平衡
算法示例:
void rotateRL(AVLTreeNode*& root) {
AVLTreeNode* currL = root;
AVLTreeNode* currR = currL->rightTree;
root = currR->leftTree;
currL->rightTree = root->leftTree;
root->leftTree = currL;
if (root->bf == 1)
currL->bf = -1;
else
currL->bf = 0;
currR->leftTree = root->rightTree;
root->rightTree = currR;
if (root->bf >= 0)
currR->bf = 0; else
currR->bf = 1;
root->bf = 0;
}
图示过程:
完整插入代码
AVLTreeNode.h
#pragma once
#ifndef AVLTREENODE_H
#define AVLTREENODE_H
#include <iostream>
#include <vector>
using namespace std;
class AVLTreeNode
{
public:
int val;
int bf; // 平衡因子
AVLTreeNode* leftTree;
AVLTreeNode* rightTree;
AVLTreeNode() :val(0), bf(0), leftTree(NULL), rightTree(NULL) {}
AVLTreeNode(int valable) :val(valable), bf(0), leftTree(NULL), rightTree(NULL) {}
AVLTreeNode(int valable, int be, AVLTreeNode* lf, AVLTreeNode* rf) :val(valable), bf(be), leftTree(lf), rightTree(rf) {}
AVLTreeNode* setAVLTree(vector<int> nums);
};
#endif // !AVLTREENODE_H
AVLTreeNode.cpp
#include "AVLTreeNode.h"
#include <iostream>
#include <stack>
#include <assert.h>
AVLTreeNode* AVLTreeNode::setAVLTree(vector<int> nums)
{
AVLTreeNode* curr_fa = NULL, *root, *curr_ch;
if (nums.empty())return NULL;
root = new AVLTreeNode(nums[0]);
curr_ch = root;
stack<AVLTreeNode*>set_way_save;
for (int i = 1; i < nums.size(); i++) {
while (curr_ch) // 查找应该插入的位置
{
if (nums[i] == curr_ch->val) {
break;
continue;
}
set_way_save.push(curr_ch);
if (nums[i] < curr_ch->val)curr_ch = curr_ch->leftTree;
else curr_ch = curr_ch->rightTree;
}
AVLTreeNode* node = new AVLTreeNode(nums[i]);
curr_ch = set_way_save.top();
if (node->val < curr_ch->val)
curr_ch->leftTree = node;
else
curr_ch->rightTree = node;
while (!set_way_save.empty()) {
curr_ch = set_way_save.top();
set_way_save.pop();
if (curr_ch->leftTree == node)
curr_ch->bf--;
else
curr_ch->bf++;
if (curr_ch->bf == 0)break;
else if (curr_ch->bf == 1 || curr_ch->bf == -1) {
node = curr_ch;
}
else
{
if (curr_ch->bf < 0) {
if (node->bf < 0)
rotateRR(curr_ch);
else
rotateLR(curr_ch);
}
else {
if (node->bf < 0)
rotateRL(curr_ch);
else
rotateLL(curr_ch);
}
break;
}
}
}
return root;
}
void rotateLL(AVLTreeNode*& root) {
AVLTreeNode* currL = root;
root = currL->rightTree;
currL->rightTree = root->leftTree;
root->leftTree = currL;
root->bf = currL->bf = 0;
}
void rotateRR(AVLTreeNode*& root) {
AVLTreeNode* curr = root;
root = curr->leftTree;
curr->leftTree = root->rightTree;
root->rightTree = curr;
root->bf = curr->bf = 0;
}
void rotateLR(AVLTreeNode*& root) {
AVLTreeNode* currL = root->leftTree;
AVLTreeNode* currR = root;
root = currL->rightTree;
currL->rightTree = root->leftTree;
root->leftTree = currL;
if (root->bf <= 0)currL->bf = 0;
else
currL->bf = -1;
currR->leftTree = root->rightTree;
root->rightTree = currR;
if (root->bf == -1)
currR->bf = 1;
else
currR->bf = 0;
root->bf = 0;
}
void rotateRL(AVLTreeNode*& root) {
AVLTreeNode* currL = root;
AVLTreeNode* currR = currL->rightTree;
root = currR->leftTree;
currL->rightTree = root->leftTree;
root->leftTree = currL;
if (root->bf == 1)
currL->bf = -1;
else
currL->bf = 0;
currR->leftTree = root->rightTree;
root->rightTree = currR;
if (root->bf >= 0)
currR->bf = 0; else
currR->bf = 1;
root->bf = 0;
}