平衡二叉树(AVL)的基本操作

AVL树的插入、创建和删除。主要是参考中国大学MOOC浙大版数据结构。

#include<bits/stdc++.h>
using namespace std;
/* AVL基本操作: 00)插入 01)创建 02)删除 */

/* AVL: 1)是一棵空树 2)具有下列性质的二叉树: 1)若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。 2)每个结点的左右子树高度差最大为 1 特点: 树高为log2(n) */

/* 四种旋转 1)单左旋转: 破坏者在被破坏者(A)左孩子(B)的左子树上:B上升、A下沉、B右挂在A左上 A->left = B->right; B->right = A; 2)单右选择: 破坏者在被破坏者(A)右孩子(B)的右孩子上:B上升、A下沉、B左挂在A右上 A->right = B->left; B->left = A; 3)左右旋转: 破坏者在被破坏者(A)左孩子(B)的右子树上: B做单右旋转; A做单左旋转; 4)右左旋转: 破坏者在被破坏者(A)右孩子(B)的左子树上: B做单左旋转; A做单右旋转; */
//AVL结点结构 
typedef class Node
{
    public:
        int val;
        Node *left;
        Node *right;
        int height;
        Node(){ left = right = NULL; }
        Node(int tval){ val = tval; left = right = NULL; }
} *AVL;

/* 单左旋转: 破坏者在被破坏者(A)左孩子(B)的左子树上:B上升、A下沉、B右挂在A左上 A->left = B->right; B->right = A; 必须保证 A有左子树 */ 
AVL singleLeftRotation(AVL root)
{
    AVL rl = root->left;
    root->left = rl->right;
    rl->right = root;
    return rl;
}

/* 单右旋转 破坏者在被破坏者(A)右孩子(B)的右孩子上:B上升、A下沉、B左挂在A右上 A->right = B->left; B->left = A; 必须保证 A有右子树 */
AVL singleRightRotation(AVL root)
{
    AVL rr = root->right;
    root->right = rr->left;
    rr->left = root;
    return rr;
} 

/* 左右旋转 破坏者在被破坏者(A)左孩子(B)的右子树上: B做单右旋转; A做单左旋转; 必须保证 A的左孩子和B的右孩子存在 */
AVL leftRightRotation(AVL root)
{
    root->left = singleRightRotation(root->left);
    return singleLeftRotation(root);
} 

/* 右左旋转 破坏者在被破坏者(A)右孩子(B)的左子树上: B做单左旋转; A做单右旋转; */
AVL rightLeftRotation(AVL root)
{
    root->right = singleLeftRotation(root->right);
    return singleLeftRotation(root);
} 
/* 插入 1)root为空时,插入结点 2)root的值小于插入的值时: 递归到右子树 退栈时如果 右子树的高度 - 左子树的高度 == 2: 插入右子树的左子树时,右左旋转 插入右子树的右子树时,单右旋转 3)root的值大于插入的值时: 递归到左子树 退栈时如果 左子树的高度 - 右子树的高度 == 2: 插入左子树的左子树时,单左旋转 插入左子树的右子树时,左右旋转 4)更新 root的高度 */
int getHeight(Node *node){ return node == NULL ? 0 : node->height; }
AVL insert(AVL root, Node* node)
{
    if(root == NULL)
        root = node;
    else if(root->val < node->val){
        root->right = insert(root->right, node);    //出来之后 root->right一定不为空 
        if(getHeight(root->right) - getHeight(root->left) == 2)
            if(node->val < root->right->val)
                root = leftRightRotation(root);
            else
                root = singleRightRotation(root); 
    }
    else if(root->val > node->val){
        root->left = insert(root->left, node);
        if(getHeight(root->left) - getHeight(root->right) == 2)
            if(node->val < root->right->val)
                root = singleLeftRotation(root);
            else
                root = rightLeftRotation(root);
    }
    root->height = max(getHeight(root->left), getHeight(root->right)) + 1;
}

AVL create()
{
    int n, val;
    cin >> n;
    AVL root = NULL;
    for(int i = 0; i < n; i++)
    {
        cin >> val;
        root = insert(root, new Node(val));
    }
    return root;
}

/* 删除 1)root的值等于需删除的值时:右子树最小值替换root值,删除原右子树最小值 2)root的值为空时:返回root 3)root的值大于需删除的值时:递归左子树,退栈时若 右子树的高 - 左子树的高 == 2,判断右子树确定旋转方式 4)root的值小于需删除的值时:递归左子树,退栈时若 左子树的高 - 右子树的高 == 2,判断左子树确定旋转方式 */
AVL del(AVL root, int val)
{
    if(root == NULL)
        return root;
    else if(root->val < val){
        root->right = del(root->right, val);    //递归右子树 
        if(getHeight(root->left) - getHeight(root->right) == 2)
        {
            AVL temp = root->left;
            //temp的左子树高于右子树时:单左旋转
            //temp的右子树高于左子树时:左右旋转 
            if(getHeight(temp->left) > getHeight(temp->right))
                root = singleLeftRotation(root);
            else
                root = leftRightRotation(root);
        }
    }else if(root->val > val){
        root->left = del(root->left, val);
        if(getHeight(root->right) - getHeight(root->left) == 2)
        {
            AVL temp = root->right;
            //temp的左子树高于右子树时:右左旋转
            //temp的右子树高于左子树时:单右旋转 
            if(getHeight(temp->left) > getHeight(temp->right))
                root = rightLeftRotation(root);
            else
                root = singleRightRotation(root);
        }
    }else{
        //若左子树为空,右子树上升;右子树为空,左子树上升 
        //左右都不空时:用右子树最小值替换根的值,递归右子树删除原右子树最小值 
        if(root->left == NULL || root->right == NULL)
            return root->left == NULL ? root->right : root->left;
        AVL temp = root->right;
        while(temp->left != NULL)
            temp = temp->left;
        root->val = temp->val;
        root->right = del(root->right, root->val);
        return root;
    }
    //更新这次删除造成的高度的改变 
    root->height = max(getHeight(root->right), getHeight(root->left)) + 1;
}
void print_levelOrder_noLayered(AVL root)
{
    AVL pointer = root;
    int f = 0, t = 0;   //头、尾。模拟队列 
    AVL arr[1010]; if(pointer != NULL) arr[t++] = pointer; while(t > f) { pointer = arr[f++]; cout << pointer->val; if(pointer->left != NULL) arr[t++] = pointer->left; if(pointer->right != NULL) arr[t++] = pointer->right; } } int main() { AVL root = create(); print_levelOrder_noLayered(root); cout << endl; AVL d = del(root, 2); print_levelOrder_noLayered(d); return 0; } /* input: 5 2 4 1 3 0 AVL: 2 1 4 0 3 */
    原文作者:平衡二叉树
    原文地址: https://blog.csdn.net/qq_38206090/article/details/81708103
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞