一、AVL树的节点平衡旋转
AVL是绝对的平衡树,增删查都可以达到log(n)
二、AVL树插入删除代码实现
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
template<typename T>
class AVLTree
{
public:
AVLTree()
:_root(nullptr){}
~AVLTree(){}
//AVL插入操作接口
void insert(const T &val)
{
_root = insert(_root, val);
}
//AVL删除操作接口
void remove(const T& val)
{
_root = remove(_root, val);
}
private:
//定义AVL树节点类型
struct Node
{
Node(T data = T())
:_data(data),
_left(nullptr),
_right(nullptr),
_height(1)
{}
int _data;
Node* _left;
Node* _right;
int _height;
};
Node* _root;
//返回节点高度值
int height(Node* node)
{
return node == nullptr ? 0 : node->_height;
}
//右旋操作,以参数node为轴做右旋转操作,并把新的根节点返回
Node* rightRotate(Node* node)
{
//节点旋转
Node* child = node->_left;
node->_left = child->_right;
child->_right = node;
//高度更新
node->_height = max(height(node->_left), height(node->_right)) + 1;
child->_height = max(height(child->_left), height(child->_right)) + 1;
return child;
}
//左旋操作,以参数node为轴做左旋转操作,并把新的根节点返回
Node* leftRotate(Node* node)
{
Node* child = node->_right;
node->_right = child->_left;
child->_left = node;
node->_height = max(height(node->_left), height(node->_right)) + 1;
child->_height = max(height(child->_left), height(child->_right)) + 1;
return child;
}
//左平衡操作,以参数node为轴做左-右旋转操作,并把新的根节点返回
Node* leftBalance(Node* node)
{
node->_left = leftRotate(node->_left);
return rightRotate(node);
}
//右平衡操作,以参数node为轴做右-左旋转操作,并把新的根节点返回
Node* rightBalance(Node* node)
{
node->_right = leftRotate(node->_right);
return leftRotate(node);
}
//AVL插入操作实现
Node* insert(Node* node, const T& val)
{
//递归结束,找到插入位置
if (node == nullptr)
{
return new Node(val);
}
if (node->_data > val)
{
node->_left = insert(node->_left, val);
//添加1 在递归回溯是判断节点是否失衡,node的左子树太高,node失衡了
if (height(node->_left) - height(node->_right) > 1)
{
if (height(node->_left->_left) >= height(node->_left->_right))
{
//节点失衡,由于左孩子的左子树太高
node = rightRotate(node);
}
else
{
//节点失衡,由于左孩子的右子树太高
node = leftBalance(node);
}
}
}
else if (node->_data < val)
{
node->_right = insert(node->_right, val);
//添加2 在递归回溯是判断节点是否失衡,node的右子树太高,
if (height(node->_right) - height(node->_left) > 1)
{
if (height(node->_right->_right) >= height(node->_right->_left))
{
//节点失衡,由于右孩子的右子树太高
node = leftRotate(node);
}
else
{
//节点失衡,由于右孩子的左子树太高
node = rightBalance(node);
}
}
}
else
{
//找到相同节点了,不用再往下递归了,直接向上回溯
return node;
}
//添加3 因为子树中增加了新的节点,在递归回溯时检测更新节点高度
node->_height = max(height(node->_left), height(node->_right)) + 1;
return node;
}
Node* remove(Node* node, const T& val)
{
if (node == nullptr)
{
return nullptr;
}
if (node->_data > val)
{
node->_left = remove(node->_left, val);
//左子树删除节点,会造成右子树偏高
if (height(node->_right) - height(node->_left) > 1)
{
//右孩子的右子树太高
if (height(node->_right->_right) >= height(node->_right->_left))
{
node = leftRotate(node);
}
//右孩子的左子树太高
else
{
node = rightBalance(node);
}
}
}
else if (node->_data < val)
{
node->_right = remove(node->_right, val);
//右子树删除节点,会造成左子树偏高
if (height(node->_left) - height(node->_right) > 1)
{
//左孩子的左子树太高
if (height(node->_left->_left) >= height(node->_left->_right))
{
node = rightRotate(node);
}
//左孩子的右子树太高
else
{
node = leftBalance(node);
}
}
}
else
{
//找到了,先处理有两个孩子的节点删除情况
if (node->_left != nullptr && node->_right != nullptr)
{
//为了避免删除前驱或者后继节点造成节点失衡,谁高删谁
if (height(node->_left) >= height(node->_right))
{
//删前驱
Node* pre = node->_left;
while (pre->_right != nullptr)
{
pre = pre->_right;
}
node->_data = pre->_data;
node->_left = remove(node->_left, pre->_data);
}
else
{
//删后继
Node* post = node->_right;
while (post->_left != nullptr)
{
post = post->_left;
}
node->_data = post->_data;
node->_right = remove(node->_right, post->_data);
}
}
else
{
Node* child = node->_left;
if (node->_right != nullptr)
{
child = node->_right;
}
delete node;
return child;
}
}
node->_height = max(height(node->_left), height(node->_right)) + 1;
return node;
}
};
int main()
{
AVLTree<int> avl;
for (int i = 1; i <= 10; i++)
{
avl.insert(i);
}
avl.remove(10);
avl.remove(9);
avl.remove(6);
avl.remove(1);
avl.remove(2);
avl.remove(3);
return 0;
}