关于AVL树及其实现

BST是一种可以实现快速查找的有序数据结构,但其性能受输入元素顺序的影响,比如输入9,8,7,6这样的有序序列,得到的就是一颗极不平衡的二叉树,甚至退化至单链表。为了改善这一点,延伸出了许多以其为基础的二叉树,如红黑树,AVL数,SB树等,他们的区别在于平衡的标准不一,接下来我们探讨下其中的AVL树。
AVL树判断平衡的标准很简单,就是该节点左右子树的高度差要不大于1,若是不满足,则进行相应的位置调整。可以列出如下不平衡的四种情况,红色的点即为不满足要求的点。在这里插入图片描述
对于RR和LL型,需要分别进行左旋和右旋。而对于RL型则要先右旋再左旋,对于LR型要先左旋再右旋。旋转过程相对简单,代码如下。

 treenode<T> *leftrotation(treenode<T> * cur){
        treenode<T> *tmp = cur->right;
        cur->right = tmp->left;
        tmp->left = cur;
        return tmp;
    }

    treenode<T> *rightrotation(treenode<T> *cur){
        treenode<T> *tmp = cur->left;
        cur->left = tmp->right;
        tmp->right = cur;
        return tmp;
    }

    treenode<T> *leftrightrotaion(treenode<T> *cur)
    {
        cur->left = leftrotation(cur->left);
        return rightrotation(cur);
    }

    treenode<T> *rightleftrotaion(treenode<T> *cur)
    {
        cur->right = rightrotation(cur->right);
        return leftrotation(cur);
    }
插入

由于每次有节点插入时,都会检测平衡条件作出调整,所以插入后破坏平衡的情况只有上述的四种情况。以递归的方式找到插入节点的位置,再在返回的途中不断检测节点的平衡条件是否满足,不满足则根据情况采取相应的旋转措施。

 treenode<T> *insert(treenode<T> *cur, T data){
        if(cur==NULL)
            return new treenode<T>(data);
        else if(data>cur->data){
            cur->right = insert(cur->right,data);
            if(getheight(cur->right)-getheight(cur->left)==2)
            {
                if(data>cur->right->data)//situation RR
                cur = leftrotation(cur);
                else if(data<cur->right->data)//RL
                cur = rightleftrotaion(cur);
            }
        }else if(data<cur->data){
              cur->left = insert(cur->left,data);
            if(getheight(cur->left)-getheight(cur->right)==2)
            {
                if(data<cur->left->data)//LL
                    cur = rightrotation(cur);
                else if(data>cur->left->data)//LR
                    cur = leftrightrotaion(cur);
            }
        }
            return cur;
    }
删除

同BST,当删除的节点左右节点不为空,则选择左树上的最右节点或者右树上的最左结点来顶替该删除的结点。若左右树只有其中一个节点不为空,则直接用不为空的节点顶替要删除的节点。删除过后需要重新判定平衡条件,同插入。

 treenode<T> *remove(treenode<T> *cur, T data){
            if(cur==NULL)
                return NULL;

            if(cur->data==data){//找到要删除的结点
                if(cur->right&&cur->left){//左右节点不为空
                    if(getheight(cur->left)>getheight(cur->right)){
                    treenode<T>*tmp = getmax(cur->left);
                    cur->data = tmp->data;
                    cur->left = remove(cur->left,tmp->data);
                    }else{
                        treenode<T>*tmp = getmin(cur->right);
                        cur->data = tmp->data;
                        cur->right = remove(cur->right,tmp->data);
                    }
                }else{
                    treenode<T>*tmp = cur;
                    if(cur->left==NULL)
                        cur = cur->right;
                    else if(cur->right==NULL)
                        cur = cur->left;
                    delete tmp;
                    return cur;
                }
            }else if(cur->data>data){
                       cur->left = remove(cur->left,data);
                       if(getheight(cur->right)-getheight(cur->left)==2)
                       {
                           if(getheight(cur->right->left)>getheight(cur->right->right))
                           cur = rightleftrotaion(cur);
                           else
                           cur = leftrotation(cur);
                       }
            }else if(cur->data<data){
                        cur->right = remove(cur->right,data);
                        if(getheight(cur->left)-getheight(cur->right)==2)
                        {
                            if(getheight(cur->left->right)>getheight(cur->left->left))
                            cur = leftrightrotaion(cur);
                            else
                            cur = rightrotation(cur);
                        }
            }
            return cur;
     }

查找,遍历打印等同BST。
完整代码

template<typename T>
struct treenode{
    T data;
    treenode<T> *left;
    treenode<T> *right;
    treenode(T a,treenode<T> *l = NULL,treenode<T> *r = NULL):data(a),left(l),right(r){}
};

template<typename T>
class AVLTree
{
private:
    treenode<T> *head;
    void destroybst(treenode<T> *Node){
        if(Node==NULL)
            return ;

        destroybst(Node->left);
        destroybst(Node->right);
         std::cout<<"delete point "<<std::to_string(Node->data)<<std::endl;
        delete Node;

    }

    treenode<T> *insert(treenode<T> *cur, T data){
        if(cur==NULL)
            return new treenode<T>(data);
        else if(data>cur->data){
            cur->right = insert(cur->right,data);
            if(getheight(cur->right)-getheight(cur->left)==2)
            {
                if(data>cur->right->data)//situation RR
                cur = leftrotation(cur);
                else if(data<cur->right->data)//RL
                cur = rightleftrotaion(cur);
            }
        }else if(data<cur->data){
              cur->left = insert(cur->left,data);
            if(getheight(cur->left)-getheight(cur->right)==2)
            {
                if(data<cur->left->data)//LL
                    cur = rightrotation(cur);
                else if(data>cur->left->data)//LR
                    cur = leftrightrotaion(cur);
            }
        }
            return cur;
    }

     treenode<T> *remove(treenode<T> *cur, T data){
            if(cur==NULL)
                return NULL;

            if(cur->data==data){
                if(cur->right&&cur->left){
                    if(getheight(cur->left)>getheight(cur->right)){
                    treenode<T>*tmp = getmax(cur->left);
                    cur->data = tmp->data;
                    cur->left = remove(cur->left,tmp->data);
                    }else{
                        treenode<T>*tmp = getmin(cur->right);
                        cur->data = tmp->data;
                        cur->right = remove(cur->right,tmp->data);
                    }
                }else{

                    treenode<T>*tmp = cur;
                    if(cur->left==NULL)
                        cur = cur->right;
                    else if(cur->right==NULL)
                        cur = cur->left;
                    delete tmp;
                    return cur;
                }
            }else if(cur->data>data){
                       cur->left = remove(cur->left,data);
                       if(getheight(cur->right)-getheight(cur->left)==2)
                       {
                           if(getheight(cur->right->left)>getheight(cur->right->right))//situation RR
                           cur = rightleftrotaion(cur);
                           else
                           cur = leftrotation(cur);
                       }

            }else if(cur->data<data){
                        cur->right = remove(cur->right,data);
                        if(getheight(cur->left)-getheight(cur->right)==2)
                        {
                            if(getheight(cur->left->right)>getheight(cur->left->left))//situation RR
                            cur = leftrightrotaion(cur);
                            else
                            cur = rightrotation(cur);
                        }
            }
            return cur;
     }



    int getheight(treenode<T> *p){
        if(p==NULL)
            return 0;

        int left = 1 + getheight(p->left);
        int right = 1 + getheight(p->right);
        return max(left,right);
    }

    treenode<T> *getmin(treenode<T> *p){
        treenode<T> *tmp = p;
        while(tmp->left!=NULL)
            tmp = tmp->left;

        return tmp;
    }

    treenode<T> *getmax(treenode<T> *p){
        treenode<T>* tmp = p;
        while(tmp->right!=NULL)
            tmp = tmp->right;

        return tmp;
    }


    treenode<T> *leftrotation(treenode<T> * cur){
        treenode<T> *tmp = cur->right;
        cur->right = tmp->left;
        tmp->left = cur;
        return tmp;
    }

    treenode<T> *rightrotation(treenode<T> *cur){
        treenode<T> *tmp = cur->left;
        cur->left = tmp->right;
        tmp->right = cur;
        return tmp;
    }

    treenode<T> *leftrightrotaion(treenode<T> *cur)
    {
        cur->left = leftrotation(cur->left);
        return rightrotation(cur);
    }

    treenode<T> *rightleftrotaion(treenode<T> *cur)
    {
        cur->right = rightrotation(cur->right);
        return leftrotation(cur);
    }



public:
    AVLTree(T data){
        head = new treenode<T>(data);
    }

    void node_insert(T data){
         head = insert(head,data);
    }

    void node_remove(T data)
    {
         remove(head,data);
    }

    void preprintf(treenode<T> *Node){
        if(Node==NULL)
            return ;
        stack<treenode<T> *> list;
        treenode<T> *p = Node;
        while(!list.empty() || p!=NULL){

            while(p)
            {
                cout<<p->data<<" ";
                list.push(p);
                p = p->left;
            }

            p = list.top();
            list.pop();
            p = p->right;

        }
            cout<<endl;
    }

    void backprintf(treenode<T> *Node){
            if(Node == NULL)
                return ;

            treenode<T> *cur = Node;
           treenode<T> *flag = NULL;
            stack<treenode<T> *> list;
            while(cur)
            {
                list.push(cur);
                cur = cur->left;
            }

            while(!list.empty())
            {
                cur = list.top();
                list.pop();
                if(cur->right==NULL || cur->right == flag)
                {
                    cout<<cur->data<<" ";
                    flag = cur;
                }else{
                    list.push(cur);
                    cur = cur->right;
                    while(cur)
                    {
                        list.push(cur);
                        cur = cur->left;
                    }

                }
            }
            return ;
    }

    treenode<T> * findnode(T data){
        treenode<T> * tmphead = head;
        while(tmphead!=NULL)
        {
            if(tmphead->data==data)
                return tmphead;
            else{
                if(data>tmphead->data)
                    tmphead = tmphead->right;
                else
                    tmphead = tmphead->left;
            }
        }
        return NULL;
    }

    ~AVLTree(){
        destroybst(head);
    }

    treenode<T> * gethead(){
        return head;
    }

};

void AVLtest()
{
    AVLTree<int> test(10);
    test.node_insert(9);
    test.node_insert(6);
    test.node_insert(17);
    test.node_insert(18);

    test.preprintf(test.gethead());
       test.node_remove(9);
       test.node_remove(17);
        test.preprintf(test.gethead());

}

int main()
{
    AVLtest();
    return 0;
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值