AVL树模板

  AVL树也是一种搜索二叉树(BST),即左孩纸比父节点小,右孩纸比父节点大。AVL树的插入就是通过遍历找到合适的位置插入,插入后可能会导致高度差大于1,所以需要通过旋转操作进行自平衡。AVL树的删除,找到删除节点,然后找到其子节点下最接近该节点val值的叶子节点,然后把该节点的val赋值为叶子节点的val,然后就转换成删除该节点下某一叶子节点了。最后进行自平衡调整。比如一个二叉树。

        5

       3           6

     1          4             7

  0     2

(5的左右节点3,6),3的左右节点是(1,4),1的左右节点是(0,2)

,准备删除3,找到3节点的位置,然后从3的孩纸节点中找到最接近他的叶子节点(2),然后把3节点的值改成2

        5

       2           6

     1          4             7

  0     2

 然后题目就变成删除val为2的节点了。

  花了半天时间学习AVL树,AVL树只要有LL,RR,LR,RL四种旋转操作,动态增加与减少都需要四种操作结合。AVL树比普通二叉树的结构体多了一个高度,用于保证左右子节点高度差小于2。在计算高度的时候,最好自己写一个函数,因为要判断是否为NULL,NULL则表示为0。如果用指针去取高度,为NULL的时候会报错。并且在计算高度差的时候,要注意是左节点减去右节点还是右节点减去左节点。

  主要灵感来源于:http://blog.csdn.net/whucyl/article/details/17289841

  

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<queue>
#include<algorithm>
#include<cmath>
using namespace std;

struct Node
{
    int val;
    int height;
    Node* left;
    Node* right;
    Node()
    {
        height = 1;
        left = NULL;
        right = NULL;
    }
    //更新高度
    void UpdateHeight()
    {
        int leftheight = left ? left->height : 0;
        int rightheight = right ? right->height : 0;
        height = max(leftheight,rightheight)+1;
    }
    //左右子孩子高度差
    int DisHeight()
    {
        int leftheight = left ? left->height : 0;
        int rightheight = right ? right->height : 0;
        return leftheight-rightheight;
    }
};

Node* LL(Node* anode)
{
    Node* bnode = anode->left;
    Node* cnode = bnode->right;
    bnode->right = anode;
    anode->left = cnode;
    //更新高度时,anode一定要先更新
    anode->UpdateHeight();
    bnode->UpdateHeight();
    return bnode;
}

Node* RR(Node* anode)
{
    Node* bnode = anode->right;
    Node* cnode = bnode->left;
    bnode->left = anode;
    anode->right = cnode;
    anode->UpdateHeight();
    bnode->UpdateHeight();
    return bnode;
}

Node* LR(Node* anode)
{
    anode->left = RR(anode->left);
    return LL(anode);
}

Node* RL(Node* anode)
{
    anode->right = LL(anode->right);
    return RR(anode);
}

Node* Insert(Node* node,int val)
{
    if(node == NULL)
    {
        node = new Node();
        node->val = val;
    }
    else if(val > node->val)
    {
        node->right = Insert(node->right,val);
        int disH = node->DisHeight();
        if(disH == -2)
        {
            if(val > node->right->val) node = RR(node);
            else node = RL(node);
        }
    }
    else if(val < node->val)
    {
        node->left = Insert(node->left,val);
        int disH = node->DisHeight();
        if(disH == 2)
        {
            if(val < node->left->val) node = LL(node);
            else node = LR(node);
        }
    }
    node->UpdateHeight();
    return node;
}

Node* Delete(Node* node,int val)
{
    if(node == NULL){return NULL;}
    else if(node->val < val)
    {
        node->right = Delete(node->right,val);
    }
    else if(node->val > val)
    {
        node->left = Delete(node->left,val);
    }
    else
    {
        if(node->left)
        {
            Node* nd;
            for(nd=node->left;nd->right != NULL;nd = nd->right);
            node->val = nd->val;
            node->left = Delete(node->left,nd->val);
        }
        else if(node->right)
        {
            Node* nd;
            for(nd=node->right;nd->left != NULL;nd = nd->left);
            node->val = nd->val;
            node->right = Delete(node->right,nd->val);
        }
        else
        {
            delete node;
            return NULL;
        }
    }

    if(node->DisHeight()==2)
    {
        if(node->left->DisHeight()==1)
            node = LL(node);
        else node = LR(node);
    }
    else if(node->DisHeight()==-2)
    {
        if(node->right->DisHeight()==-1)
            node = RR(node);
        else node = RL(node);
    }

    node->UpdateHeight();
    return node;
}

void pre_travel(Node* node)
{
    if(node==NULL) return;
    printf("%d ",node->val);
    pre_travel(node->left);
    pre_travel(node->right);
}
void in_travel(Node* node)
{
    if(node==NULL) return;
    in_travel(node->left);
    printf("%d ",node->val);
    in_travel(node->right);
}

int main()
{
    //test code
    Node *root = NULL;
    root = Insert(root,5);
    root = Insert(root,6);
    root = Insert(root,3);
    root = Insert(root,2);
    root = Insert(root,4);
    root = Insert(root,1);
    root = Insert(root,9);
    root = Insert(root,8);
    root = Insert(root,7);

    printf("先序遍历:
");
    pre_travel(root);
    printf("
");
    printf("中序遍历:
");
    in_travel(root);
    printf("
");

    root = Delete(root,6);
    root = Delete(root,1);
    printf("
先序遍历:
");
    pre_travel(root);
    printf("
");
    printf("中序遍历:
");
    in_travel(root);
    printf("
");
    return 0;
}

PAT1066,简单AVL的插入操作。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;

struct Node
{
    int val;
    int H;
    Node* left;
    Node* right;
    Node()
    {
        H = 1;
        left = NULL;
        right = NULL;
    }
    int LH(){return left?left->H:0;}
    int RH(){return right?right->H:0;}
    void UpdateH(){H = max(LH(),RH())+1;}
    int DisH(){return LH() - RH();}
};

Node* LL(Node* anode)
{
    Node *bnode = anode->left;
    Node *cnode = bnode->right;
    bnode->right = anode;
    anode->left = cnode;
    anode->UpdateH();
    bnode->UpdateH();
    return bnode;
}

Node* RR(Node* anode)
{
    Node *bnode = anode->right;
    Node *cnode = bnode->left;
    bnode->left = anode;
    anode->right = cnode;
    anode->UpdateH();
    bnode->UpdateH();
    return bnode;
}

Node* LR(Node* anode)
{
    anode->left = RR(anode->left);
    return LL(anode);
}

Node* RL(Node* anode)
{
    anode->right = LL(anode->right);
    return RR(anode);
}

Node* Insert(Node* node,int val)
{
    if(node==NULL)
    {
        node = new Node();
        node->val = val;
    }
    else if(val > node->val)
    {
        node->right = Insert(node->right,val);
        if(node->DisH()==-2)
        {
            if(val > node->right->val) node = RR(node);
            else node = RL(node);
        }
    }
    else if(val < node->val)
    {
        node->left = Insert(node->left,val);
        if(node->DisH()==2)
        {
            if(val < node->left->val) node = LL(node);
            else node = LR(node);
        }
    }

    node->UpdateH();
    return node;
}

int main()
{
    int n;
    scanf("%d",&n);
    Node* root = NULL;
    for(int i=0;i<n;++i)
    {
        int val;
        scanf("%d",&val);
        root = Insert(root,val);
    }
    printf("%d
",root->val);
    return 0;
}
View Code

PAT1123,简单AVL的插入与已知广度遍历与宽度遍历的关系

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<vector>
#include<algorithm>
#include<queue>
using namespace std;
int n;

struct Node
{
    int val;
    int H;
    Node* left;
    Node* right;
    Node()
    {
        H = 1;
        left = NULL;
        right = NULL;
    }
    int LH(){return left?left->H:0;}
    int RH(){return right?right->H:0;}
    void UpdateH(){H = max(LH(),RH())+1;}
    int DisH(){return LH()-RH();}
};

Node* LL(Node* anode)
{
    Node* bnode = anode->left;
    Node* cnode = bnode->right;
    bnode->right = anode;
    anode->left = cnode;
    anode->UpdateH();
    bnode->UpdateH();
    return bnode;
}
Node* RR(Node* anode)
{
    Node* bnode = anode->right;
    Node* cnode = bnode->left;
    bnode->left = anode;
    anode->right = cnode;
    anode->UpdateH();
    bnode->UpdateH();
    return bnode;
}

Node* LR(Node* anode)
{
    anode->left = RR(anode->left);
    return LL(anode);
}

Node* RL(Node* anode)
{
    anode->right = LL(anode->right);
    return RR(anode);
}

Node* Insert(Node* node,int val)
{
    if(node==NULL)
    {
        node = new Node();
        node->val = val;
    }
    else if(val < node->val)
    {
        node->left = Insert(node->left,val);
        if(node->DisH()==2)
        {
            if(val < node->left->val) node=LL(node);
            else node=LR(node);
        }
    }
    else if(val > node->val)
    {
        node->right = Insert(node->right,val);
        if(node->DisH()==-2)
        {
            if(val > node->right->val) node=RR(node);
            else node=RL(node);
        }
    }
    node->UpdateH();
    return node;
}

vector<int> vi;
void bfs(Node* node)
{
    queue<Node*> qn;
    qn.push(node);
    bool bFirst = true;
    while(!qn.empty())
    {
        Node* temp = qn.front();
        qn.pop();
        if(temp->left){qn.push(temp->left);}
        if(temp->right){qn.push(temp->right);}
        if(bFirst) bFirst = false;
        else printf(" ");
        printf("%d",temp->val);
        vi.push_back(temp->val);
    }
    printf("
");
}

int Index = 0;
int a[30],b[30];

void Travel(Node* node)
{
    if(node == NULL) return;
    Travel(node->left);
    b[Index++] = node->val;
    Travel(node->right);
}

void Travel2(int k)
{
    if(k >= n) return;
    Travel2(2*k+1);
    a[k] = b[Index++];
    Travel2(2*k+2);
}

int main()
{
    scanf("%d",&n);
    Node *root = NULL;
    for(int i=0;i<n;++i)
    {
        int val;
        scanf("%d",&val);
        root = Insert(root,val);
    }
    bfs(root);
    Travel(root);
    Index = 0;
    Travel2(0);
    bool bOK = true;
    for(int i=0;i<n;++i)
        if(a[i] != vi[i]){bOK = false;break;}
    if(bOK) printf("YES
");
    else printf("NO
");
    return 0;
}
View Code

 思考题:已知AVL数的插入顺序,求根节点值(有没有简单的方法)?

原文地址:https://www.cnblogs.com/jlyg/p/7521434.html