AVLTree 代码优化

</pre><pre name="code" class="html">/**********************************************************************
 *      Title: A Plain Implementation of AVLTree
 *
 *      Motivation: Like the Plain Style Codes
 *
 *      Author: stinkaroo
 *
 *      Email: 190690276@qq.com
 *
 *      Date: 2016-5-20
 *
 *      Reference: http://www.cppblog.com/cxiaojia/
 *                     archive/2012/08/20/187776.html
 *
 *      Other tips: Since the original article is written by Chinese,
 *                      so I mixed English and Chinese in my codes.
 **********************************************************************/

#include <stdio.h>
#include <iostream>
using namespace std;

//外部提供的访问数据的函数
void visit(int data);


/**********************Node of AVLTree******************************/
template<class T>
class TreeNode
{
public:
    TreeNode(): leftChild_(NULL), rightChild_(NULL), height_(1){}

public:
    TreeNode *leftChild_;  //指向左儿子的地址
    TreeNode *rightChild_; //指向右儿子的地址
    T         data_;   //数据元素
    int       height_; //以此节点为根的树的高度
};
/**********************Node of AVLTree******************************/


/**********************Structure of AVLTree******************************/
template<class T>
class AVLTree
{
public:
    AVLTree():root(NULL){}

    //查找, 未找到返回空指针
    TreeNode<T>* Search(T x);

    //插入值, 插入成功返回0值, 插入失败返回-1
    int Insert(T x);

    //删除值, 删除成功返回0值, 删除失败返回-1
    int Delete(T x);

    //遍历平衡二叉树
    void Traversal(void (*visit)(T));

private:
    TreeNode<T>* Search(TreeNode<T>* node, T x); //查找,仅声明,未实现
    int Insert(TreeNode<T> *&node, T x); //插入
    int Delete(TreeNode<T> *&node, T x); //删除
    void InOrderTraversal(TreeNode<T> *node, void(*visit)(T)); //中序遍历

    //通过旋转操作让树重新平衡, type == 0 表示可能左树过高,
    // type == 1 表示可能右树过高
    void ReBalance(TreeNode<T> *&node, int type);

    //旋转函数以实际旋转方向命名
    void RotateRight(TreeNode<T> *&node); //左左情形, 树向右旋转(顺时针方向)
    void RotateLeft(TreeNode<T> *&node);  //右右情形, 树向左旋转(逆时针方向)
    void RotateLR(TreeNode<T> *&node); //左右情形, 先向左旋转, 再向右旋转
    void RotateRL(TreeNode<T> *&node); //右左情形, 先向右旋转, 再向左旋转

    int Height(TreeNode<T> *node);//求树的高度
    int Bigger(int a, int b);//求较大值

private:
    TreeNode<T> *root;//根节点
};
/**********************Structure of AVLTree******************************/


/**********************Public Interface of AVLTree***********************/
//NO.1 查找结点
template<class T>
TreeNode<T>* AVLTree<T>::Search(T x)
{
    return Search(root, x);
}

//NO.2 插入结点
template<class T>
int AVLTree<T>::Insert(T x)
{
    Insert(root, x);
}

//NO.3 删除结点
template<class T>
int AVLTree<T>::Delete(T x)
{
    Delete(root, x);
}

//NO.4 遍历平衡二叉树
template<class T>
void AVLTree<T>::Traversal(void(*visit)(T))
{
    InOrderTraversal(root, visit);
}
/**********************Public Interface of AVLTree***********************/


/**********************Internal Private Function of AVLTree**************/
//NO.5 查找结点
template<class T>
TreeNode<T>* AVLTree<T>::Search(TreeNode<T> *node, T x)
{
    if(node == NULL){  //未找到目标结点
        return NULL;
    }

    if(x == node->data_){
        return node;
    }
    else if(x < node->data_){
        return Search(node->leftChild_, x);
    }
    else{
        return Search(node->rightChild_, x);
    }
}

//NO.6 插入结点
template<class T>
int AVLTree<T>::Insert(TreeNode<T> *&node, T x)
{
    if(node == NULL){ //如果节点为空,就在此节点处加入x信息
        node = new TreeNode<T>();
        node->data_ = x;
        return 0;
    }

    int result = 0;
    if(x < node->data_){ //如果x小于节点的值,就继续在节点的左子树中插入x
        result = Insert(node->leftChild_, x);
        ReBalance(node, 0);
    }
    else if(x > node->data_){ //如果x大于节点的值,就继续在节点的右子树中插入x
        result = Insert(node->rightChild_, x);
        ReBalance(node, 1);
    }

    //调整结点高度值
    node->height_ = Bigger(Height(node->leftChild_), Height(node->rightChild_));

    return result;
}

//NO.7 删除结点
template<class T>
int AVLTree<T>::Delete(TreeNode<T> *&node, T x)
{
    if(node == NULL){ //没有找到值是x的节点
        return -1;
    }

    int result = 0;
    if(x < node->data_){
        result = Delete(node->leftChild_, x);//如果x小于节点的值,就继续在节点的左子树中删除x
        ReBalance(node, 1);
    }
    else if(x > node->data_){
        result = Delete(node->rightChild_, x);//如果x大于节点的值,就继续在节点的右子树中删除x
        ReBalance(node, 0);
    }
    else{ //如果相等,此节点就是要删除的节点
        result = 0;
        if(node->leftChild_ && node->rightChild_){ //此节点有两个儿子
            TreeNode<T>* temp = node->rightChild_; //temp指向节点的右儿子
            while(temp->leftChild_ != NULL){
                temp = temp->leftChild_;//找到右子树中值最小的节点
            }
            //把右子树中最小节点的值赋值给本节点
            node->data_ = temp->data_;
            Delete(node->rightChild_, temp->data_);//删除右子树中最小值的节点
            ReBalance(node, 0);
        }
        else//此节点有1个或0个儿子
        {
            TreeNode<T> *temp = node;
            if(node->leftChild_ == NULL){ //有右儿子或者没有儿子
                node = node->rightChild_;
            }
            else if(node->rightChild_== NULL){ //有左儿子
                node = node->leftChild_;
            }
            delete(temp);
            temp = NULL;
        }
    }

    node->height_ = Bigger(Height(node->leftChild_), Height(node->rightChild_)) + 1;
    return 0;
}

//NO.8 中序遍历树
template<class T>
void AVLTree<T>::InOrderTraversal(TreeNode<T>* node, void (*vist)(T))
{
    if(node == NULL){
        return;
    }

    InOrderTraversal(node->leftChild_, visit); //先遍历左子树

    vist(node->data_);  //访问数据

    InOrderTraversal(node->rightChild_, visit); //再遍历右子树
}

//NO.9 重新平衡树
template<class T>
void AVLTree<T>::ReBalance(TreeNode<T> *&node, int type)
{
    if(type == 0){ //可能左树过高, 作相应调整
        if(2 == Height(node->leftChild_) - Height(node->rightChild_)){
            if(Height(node->leftChild_->leftChild_)
                    > Height(node->leftChild_->rightChild_)){
                RotateRight(node);
            }
            else{
                RotateLR(node);
            }
        }
    }
    else if(type == 1){ //可能右树过高, 作相应调整
        if(2 == Height(node->rightChild_) - Height(node->leftChild_)){
            if(Height(node->rightChild_->rightChild_)
                    > Height(node->rightChild_->leftChild_)){
                RotateLeft(node);
            }
            else{
                RotateRL(node);
            }
        }//
    }
}

//NO.10 左左情况下的旋转
template<class T>
void AVLTree<T>::RotateRight(TreeNode<T> *&node)
{
    TreeNode<T> *node2;
    node2 = node->leftChild_;
    node->leftChild_ = node2->rightChild_;
    node2->rightChild_ = node;

    node->height_ = Bigger(Height(node->leftChild_), Height(node->rightChild_)) + 1;
    node2->height_ = Bigger(Height(node2->leftChild_), node->height_) + 1;
}

//NO.11 右右情况下的旋转
template<class T>
void AVLTree<T>::RotateLeft(TreeNode<T>* &node)
{
    TreeNode<T> *node2;
    node2 = node->rightChild_;
    node->rightChild_ = node2->leftChild_;
    node2->leftChild_ = node;

    node->height_ = Bigger(Height(node->leftChild_), Height(node->rightChild_)) + 1;
    node2->height_ = Bigger(Height(node2->rightChild_), node->height_) + 1;
}

//NO.12 左右情况的旋转
template<class T>
void AVLTree<T>::RotateLR(TreeNode<T> *&node)
{
    RotateLeft(node->leftChild_);
    RotateRight(node);
}

//NO.13 右左情况的旋转
template<class T>
void AVLTree<T>::RotateRL(TreeNode<T> *&node)
{
    RotateRight(node->rightChild_);
    RotateLeft(node);
}

//NO.14 计算以节点为根的树的高度
template<class T>
int AVLTree<T>::Height(TreeNode<T> *node)
{
    if(node != NULL)
        return node->height_;
    return 0;
}

//NO.15 求较大值
template<class T>
int AVLTree<T>::Bigger(int a, int b)
{
    return a > b ? a : b;
}

/**********************Internal Private Function of AVLTree**************/


//访问数据函数的实现
void visit(int data)
{
    cout << data << " ";
}


//简单验证程序
int main()
{
    AVLTree<int> tree;
    const int testSize = 24;

    for(int i = 0; i < testSize; i++){
        tree.Insert(i);
    }

    for(int i = 0; i < testSize; i += 2){
        tree.Delete(i);
    }

    tree.Traversal(visit);

    TreeNode<int> *a = tree.Search(15);

    cout << "\na->data_ == " << a->data_ << '\n';

    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值