AVL树(平衡二叉树)的构造

特点:平衡二叉树要求对于每一个节点来说,他的左右子树的高度之差不超过1,如果插入或者删除一个结点使得高度之差大于1,就要进行节点之间的旋转(左旋或者右旋),将二叉树重新维持在一个平衡状态
解决了二叉查找树退化成链表的问题,把插入,查找,删除时间复杂度最坏和最好情况都维持在O(logN)
旋转缺点:频繁旋转会牺牲掉O(logN)左右的时间,不过相对二叉查找树来说,时间上稳定了许多。

平衡二叉树的核心:
旋转算法
《AVL树(平衡二叉树)的构造》
1:左左形式的不平衡
2.左右形式的不平衡
3.右左形式的不平衡
4.右右形式的不平衡
1,4一组
2,3一组

对于1:左旋 3的右子树给6的左边,6变成3的右子树,3成根
确定要换的根root和左子树left,left的右子树给root的左,root变成left的右
对于4:右旋 4的左子树给2的右边,2变成4的左子树,2成根
确定要换的根root和右子树right,right的左子树给root的右然后root变成right的左
对于2:先右旋左子树,再左旋根
《AVL树(平衡二叉树)的构造》
对于3:先左旋右子书,再右旋根
代码如下:

#include <iostream>
#include <malloc.h>
#include <stack>

using namespace std;

typedef struct TreeNode
{
    int height;
    int data;
    TreeNode* leftC;
    TreeNode* rightC;
}TreeNode;

int getHeight(TreeNode* s)
{
    if (s != NULL)
    {
        return s->height;
    }
    return -1;
}

void InitTree(TreeNode** list)
{
    *list = (TreeNode*)malloc(sizeof(TreeNode));
    (*list)->height = 0;
    (*list)->leftC = NULL;
    (*list)->rightC = NULL;
}



void leftRotate(TreeNode*& root)//左左
{
    TreeNode *l1 = root;
    TreeNode *l2 = root->leftC;
    l1->leftC = l2->rightC;
    l2->rightC = l1;
    l1->height = (getHeight(l1->leftC) > getHeight(l1->rightC) ? getHeight(l1->leftC) : getHeight(l1->rightC)) + 1;
    l2->height = (getHeight(l2->leftC) > getHeight(l2->rightC) ? getHeight(l2->leftC) : getHeight(l2->rightC)) + 1;
    root = l2;
}

void rightRotate(TreeNode*& root)//右右
{
    TreeNode *l1 = root;
    TreeNode *l2 = root->rightC;
    l1->rightC = l2->leftC;
    l2->leftC = l1;
    l1->height = getHeight(l1);
    l2->height = getHeight(l2);
    root = l2;
}

///左右,先右旋,再左旋
void DoubleRotateLR(TreeNode* &n1)
{
    rightRotate(n1->leftC);
    leftRotate(n1);
}

//右左,先左旋,后右旋
void DoubleRotateRL(TreeNode* &n1)
{
    leftRotate(n1->rightC);
    rightRotate(n1);
}


void Insert(TreeNode*& node, int data)
{
    if (node == NULL)
    {
        TreeNode* tmp = (TreeNode*)malloc(sizeof(TreeNode));
        tmp->data = data;
        tmp->height = 0;
        tmp->leftC = NULL;
        tmp->rightC = NULL;
        node = tmp;
        return;
    }
    if (node->data > data)//结点的值大于data
    {
        Insert(node->leftC, data);//不断插入

        if ((getHeight(node->leftC) - getHeight(node->rightC)) == 2)
        {//说明需要左旋
            if (data < node->leftC->data)
            {
                leftRotate(node);
            }
            else
            {
                DoubleRotateLR(node);
            }
        }
        else if (node->data < data)//没有相同的值
        {
            Insert(node->rightC, data);
            //如果高度之差为2的话就失去了平衡,需要旋转
            if (2 == getHeight(node->rightC) - getHeight(node->leftC))
            {
                if (data > node->rightC->data)
                {
                    rightRotate(node);
                }
                else
                {
                    DoubleRotateRL(node);
                }
            }
        }
    }
    node->height = (getHeight(node->leftC) > getHeight(node->rightC) ? getHeight(node->leftC) : getHeight(node->rightC)) + 1;
}

void preOrder(TreeNode* node)
{
    if (node == NULL)
    {
        return;
    }
    cout << node->data << endl;
    preOrder(node->leftC);
    preOrder(node->rightC);
}

void  inOrderTraversal(TreeNode* root)//非递归中序遍历
{//先左,再中,最后右,对于每个子树也是一样的顺序
    stack<TreeNode *> S;
    while (true)
    {
        if (root)
        {
            S.push(root);
            root = root->leftC;
        }
        else
        {
            if (S.empty())
            {
                break;
            }
            root = S.top();
            cout << root->data << " ";
            S.pop();
            root = root->rightC;
        }
    }
}

void deleteNode(TreeNode* &node, int x)
{
    if (node == NULL) return; //没有找到值是x的节点

    if (x < node->data)
    {
        //如果x小于节点的值,就继续在节点的左子树中删除x
        deleteNode(node->leftC, x);
        if (2 == getHeight(node->rightC) - getHeight(node->leftC))
        {
            if (node->rightC->leftC && getHeight(node->rightC->leftC) > getHeight(node->rightC->rightC))
                DoubleRotateRL(node);
            else
                rightRotate(node);
        }
    }
    else if (x > node->data)
    {
        //如果x大于节点的值,就继续在节点的右子树中删除x
        deleteNode(node->rightC, x);
        if (2 == getHeight(node->leftC) > getHeight(node->rightC))
        {
            if (node->leftC ->rightC && getHeight(node->leftC->rightC) > getHeight(node->leftC->leftC))
                DoubleRotateLR(node);
            else
                leftRotate(node);
        }
    }
    else //如果相等,此节点就是要删除的节点
    {
        if (node->leftC && node->rightC) //此节点有两个儿子
        {
            TreeNode* ptr = node->rightC; //ptr指向节点的右儿子

            while (ptr->leftC != NULL) ptr = ptr->leftC;//找到右子树中值最小的节点
                                                      //把右子树中最小节点的值赋值给本节点
            node->data = ptr->data;
            //删除右子树中最小值的节点
            deleteNode(node->rightC, ptr->data);
            if (2 == getHeight(node->leftC) - getHeight(node->rightC))
            {
                if (node->leftC->rightC && getHeight(node->leftC->rightC) > getHeight(node->leftC->leftC))
                    DoubleRotateLR(node);
                else
                    leftRotate(node);
            }
        }
        else
        {
            TreeNode* ptr = node;
            //此节点有1个或0个儿子
            if (node->leftC == NULL) //有右儿子或者没有儿子
                node = node->rightC;
            else if (node->rightC == NULL) //有左儿子
                node = node->leftC;

            delete ptr;
            ptr = NULL;
        }
    }

    if (node)
        node->height = (getHeight(node->leftC) > getHeight(node->rightC) ? getHeight(node->leftC) : getHeight(node->rightC)) + 1;
}

int main()
{
    TreeNode *head;
    InitTree(&head);
    for (int i = 5; i > 0; --i)
    {
        Insert((*head).leftC, i);
    }
    preOrder((*head).leftC);
    inOrderTraversal((*head).leftC);
    cout << endl;
    deleteNode((*head).leftC, 1);
    inOrderTraversal((*head).leftC);
    cout << endl;
    Insert((*head).leftC, 1);
    deleteNode((*head).leftC, 4);
    inOrderTraversal((*head).leftC);
    cout << endl;
    preOrder((*head).leftC);

    return 0;
}

    原文作者:平衡二叉树
    原文地址: https://blog.csdn.net/hello_bravo_/article/details/52948871
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞