四种旋转
// 定义一个结构体表示树节点
struct Node {
int key; // 节点关键字值/key值
int height; // 节点的高度,用于AVL树的平衡因子计算
Node* left; // 指向左子树的指针
Node* right;// 指向右子树的指针
};
// 获取树的高度函数
// 如果节点为NULL,则高度为0,否则返回节点的高度值
int height(Node* N) {
if (N == NULL)
return 0;
return N->height;
}
// 创建新节点函数
// 输入关键字值,初始化一个新节点,并返回它的指针
Node* newNode(int key)
{
Node* node = new Node(); // 创建新节点
node->key = key; // 设置新节点的关键字值
node->left = NULL; // 设置新节点左子树为NULL
node->right = NULL; // 设置新节点右子树为NULL
node->height = 1; // 新节点初建时是叶子节点,高度为1
return(node); // 返回新节点的指针
}
// 获取两个整数的最大值
int max(int a, int b) {
return (a > b) ? a : b;
}
// 计算平衡因子函数
// 用于检测树是否失衡
int getBalance(Node* N) {
if (N == NULL)
return 0;
return height(N->left) - height(N->right);
}
// 添加节点
Node* insert(Node* node, int key) {
// 1. 正常的二叉搜索树插入操作
if (node == NULL) {
return(newNode(key)); // 创建新节点并返回
}
if (key < node->key) {
node->left = insert(node->left, key); // 插入左子树中
}
else if (key > node->key) {
node->right = insert(node->right, key); // 插入右子树中
}
else {
// 相等的key值,不允许插入重复元素
return node;
}
// 2. 更新节点高度
node->height = 1 + max(height(node->left), height(node->right));
// 3. 检查节点平衡因子,确定是否需要旋转
int balance = getBalance(node); // 计算平衡因子
// 根据平衡因子决定旋转策略
// 左子树高度大于右子树高度,且插入的节点在左字树的左边 -- LL
if (balance > 1 && key < node->left->key) {
return rightRotate(node); // 右旋
}
// 右子树高度大于左子树高度,且插入的节点在右子树的右边 -- RR
if (balance < -1 && key > node->right->key) {
return leftRotate(node); // 左旋
}
// 左子树高度大于右子树高度,且插入的节点在左子树的右边 -- LR
if (balance > 1 && key > node->left->key) {
return LRrotate(node); // 左-右旋
}
// 右子树高度大于左子树高度,且插入的节点在右子树的左边 -- RL
if (balance < -1 && key < node->right->key) {
return RLrotate(node); // 右-左旋
}
// 插入之后仍然平衡,无需旋转,直接返回该节点
return node;
}
// 右旋操作函数
// 输入当前节点y,返回旋转后新的根节点
Node* rightRotate(Node* y) {
Node* x = y->left; // 保存y的左子树节点
Node* T2 = x->right; // 保存x的右子树
// 旋转操作
x->right = y; // 把y设为x的右子树
y->left = T2; // 把T2设为y的左子树
// 更新节点的高度
// 高度等于节点的左、右子树的最大高度 + 1
y->height = max(height(y->left),height(y->right)) + 1;
x->height = max(height(x->left),height(x->right)) + 1;
// 返回新的根节点
return x;
}
// 左旋操作函数,和右旋相反
Node* leftRotate(Node* x) {
Node* y = x->right;
Node* T2 = y->left;
y->left = x;
x->right = T2;
// 更新x和y节点的高度
x->height = max(height(x->left),height(x->right)) + 1;
y->height = max(height(y->left),height(y->right)) + 1;
// 返回新的根节点
return y;
}
// 左右旋操作函数 LR
// 先对节点的左子树进行左旋操作,再对节点自身进行右旋操作
Node* LRrotate(Node* node) {
node->left = leftRotate(node->left); // 对节点的左子树进行左旋操作
return rightRotate(node); // 对节点自身进行右旋操作,返回新的根节点
}
// 右左旋操作函数 RL,和左右旋相反
// 先对节点的右子树进行右旋操作,再对节点自身进行左旋操作
Node* RLrotate(Node* node) {
node->right = rightRotate(node->right); // 对节点的右子树进行右旋操作
return leftRotate(node); // 对节点自身进行左旋操作,返回新的根节点
}