数据结构之二叉平衡树

AVL树是一颗二叉查找树,又被称为平衡二叉树,它具有以下特点:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一颗平衡二叉树,在AVL树中任何结点的两个子树的高度最大差别为1.
要求根据给定的序列,按照输入顺序插入AVL树。
要求:

输入

第一行输入不定长待插入数组。

输出

输出构造完毕的AVL树的先序遍历,逐元素换行。

#include <iostream>

#include<math.h>

class Node {

public:

    Node(int elem_, Node* lchild_ = NULL, Node* rchild_ = NULL, Node* parent_ = NULL, int balance_ = 0)

    {

        _elem = elem_;

        _lchild = lchild_;

        _rchild = rchild_;

        _parent = parent_;

        _balance = balance_;

    }

    bool hasLeftChild() {//判断是否有左孩子结点

        return _lchild != NULL;

    }

    bool hasRightChild() {//判断是否有右孩子结点

        return _rchild != NULL;

    }

    bool hasParent() {//判断是否有父母结点

        return _parent != NULL;

    }

    bool isLeftChild() {//判断是否为父母结点的左孩子结点

        return _parent->_lchild == this;

    }

    bool isRightChild() {//判断是否为父母结点的右孩子结点

        return _parent->_rchild == this;

    }

public:

    int _elem = 0;

    int _balance = 0;

    int height = -1;

    Node* _lchild = NULL;

    Node* _rchild = NULL;

    Node* _parent = NULL;

};

class AVLtree {

public:

    AVLtree(Node* root_ = NULL) {

        _root = root_;

    }

    int height(Node*t)const

    {

        return t == NULL ? -1 : t->height;

    }

    void rotateL(Node*& root_) {//当前结点作根节点对应的子树左旋

        Node* k1 = root_->_rchild;

        if (k1 == nullptr)

        {

            k1 = root_;

            root_ = root_->_lchild;

            return;

        }

        root_->_rchild = k1->_lchild;

        k1->_lchild = root_;

        root_->height = fmax(height(root_->_rchild), height(root_->_lchild)) + 1;

        root_ = k1;

        return;

    }

    void rotateR(Node*& root_) {//当前结点作根节点对应的子树右旋

        Node* k1 = root_->_lchild;

        if (k1 == nullptr)

        {

            k1 = root_;

            root_ = root_->_rchild;

            return;

        }

        root_->_lchild = k1->_rchild;

        k1->_rchild = root_;

        root_->height = fmax(height(root_->_lchild), height(root_->_rchild)) + 1;

        root_ = k1;

        return;

    }

    void rebalance(Node*& node_) {//平衡AVL树

        /*需要判断一下平衡类型,LL,RR,LR,RL*/

        if (node_->_balance == 2)

        {

            if (height(node_->_lchild->_lchild) > height(node_->_lchild->_rchild)) //LL情况

                rotateR(node_);         //对危机节点进行右旋

            else                        //也就是LR情况,

            {

                rotateL(node_->_lchild); //LR情况,使危机节点的左儿子先左旋

                rotateR(node_);

            }           //再对原危机节点右旋

        }

        if (node_->_balance == -2)

        {

            if (height(node_->_rchild->_rchild) > height(node_->_rchild->_lchild))  //RR>RL

                rotateL(node_);

            else

            {

                rotateR(node_->_rchild);  //RL情况,先右旋再左旋

                rotateL(node_);

            }

            node_->height = fmax(height(node_->_lchild), height(node_->_rchild)) + 1;//更新高度

        }

        return;

    }

    void updateBalance(Node* node_) {//更新结点平衡值,保证在-1~1

        node_->_balance = height(node_->_lchild) - height(node_->_rchild);

        return;

    }

    void insert(int elem_, Node*& node_) {//插入结点

        if (node_ == nullptr)   //没有节点则新建一个

            node_ = new Node{ elem_ };

        else if (elem_ < node_->_elem)  //如果新插入的节点比当前节点更小,则插入到左边,如果插入的节点更大则插入到右方

        {

            insert(elem_, node_->_lchild);//递归插入,此处lchild为NULLPTR,递归回去会到第一个if处,会给lchild创建一个新节点

            updateBalance(node_);

            if (node_->_balance == 2)   //检测一次平衡值,只要不平衡,立刻调用平衡函数

                rebalance(node_);

        }

        else if (node_->_elem < elem_)

        {

            insert(elem_, node_->_rchild);

            updateBalance(node_);

            if (node_->_balance == -2)

                rebalance(node_);

        }

        else

            ;

        node_->height = fmax(height(node_->_lchild), height(node_->_rchild)) + 1;

    }

    void pre_order(Node* node_) {//先序遍历

        if (node_ != NULL) {

            std::cout << node_->_elem << std::endl;

            pre_order(node_->_lchild);

            pre_order(node_->_rchild);

        }

        return;

    }

public:

    Node* _root = NULL;

};

int main() {

    int data_in;

    AVLtree avltree;

    while (std::cin >> data_in) {

        avltree.insert(data_in, avltree._root);

        if (std::cin.get() == '\n') break;

    }

    avltree.pre_order(avltree._root);

    return 0;

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值