码迷,mamicode.com
首页 > 编程语言 > 详细

平衡二叉树AVL树的实现(c++STL)

时间:2017-10-21 22:30:33      阅读:518      评论:0      收藏:0      [点我收藏+]

标签:col   锁定   logs   null   child   clu   ==   平衡   重置   

#include <iostream>
using namespace std;

template<class Type> 
class AVLtree;           

template<class Type>
class TNode
{
    friend  class  AVLtree<Type>;
private:
    Type  data;
    int   balance;    // 平衡因子
    TNode<Type> *leftChild, *rightChild;
public:
    TNode(const Type &x =  Type(),TNode<Type> *left = NULL,TNode<Type> *right = NULL)
        : data(x)
        , leftChild(left)
        , rightChild(right)
        , balance(0)
    {}
};

template<class Type>
class AVLtree
{
private:
    TNode<Type>  *root;
private:
    void RightBalance(TNode<Type> * &r,bool  &action);
    void LeftBalance(TNode<Type> *&r,bool &action);
    void Insert(TNode<Type> * &root,const Type &x,bool &action);
    void LeftLeft(TNode<Type> * &r);
    void RightRight(TNode<Type> * &r);
    void LeftRight(TNode<Type> *&r);
    void RightLeft(TNode<Type> *&r);
    TNode<Type> *Parent(TNode<Type> *p,TNode<Type> *cur);
    TNode<Type> *FindNodeNext(TNode<Type> *cur);
    void DeleTNode(TNode<Type> *&cur,TNode<Type> *par);
    void Remove(TNode<Type> * &r,const Type &x,bool &action);
    void InOrder(TNode<Type> *p);
public:
    AVLtree();
    void Insert(const Type &bt);
    TNode<Type> *Parent(TNode<Type> *cur);
    void Remove(const Type &x);
    void InOrder();
};

// 右平衡处理过程
template<class Type>
void AVLtree<Type>::RightBalance(TNode<Type> * &r, bool &action)
{
    TNode<Type> *rightsub = r->rightChild, *leftsub = NULL;
    switch (rightsub->balance)   //判断右子树的平衡因子
    {
        case -1: // RR型
            r->balance = 0;
            rightsub->balance = 0;
            RightRight(r);   //RR型处理
            action = false;
            break;
        case 0:
            break;
        case 1: // RL型
            leftsub = rightsub->leftChild;  
            switch (leftsub->balance) // 判断左子树的平衡因子
            {
                case 0: // RL型
                    r->balance = 0;
                    rightsub->balance = 0;
                    leftsub->balance = 0;
                    break;
                case 1: // RLL型
                    r->balance = 0;
                    leftsub->balance = 0;
                    rightsub->balance = -1;
                    break;
                case -1: // RLR型
                    rightsub->balance = 0;
                    leftsub->balance = 0;
                    r->balance= -1;
                    break;
            }
            RightLeft(r);  // RL折线型转换处理
            action = false;
            break;
    }
}
// 折线型LR处理
template<class Type>
void AVLtree<Type>::LeftRight(TNode<Type> *&r)
{
    RightRight(r->leftChild); // 转换为LL型(一条直线)
    LeftLeft(r);  // LL型处理
}
// 折线型RL处理
template<class Type>
void AVLtree<Type>::RightLeft(TNode<Type> *&r)
{
    LeftLeft(r->rightChild);  // 先转换为RR型(一条直线)
    RightRight(r);  // RR型处理
}
// 1. 把RL转换为RR  2. LL型处理
template<class Type>
void AVLtree<Type>::LeftLeft(TNode<Type> * &r) 
{
    TNode<Type> *cur = r;          // cur暂存r
    r = r->leftChild;              // 改变r就是改变根
    cur->leftChild = r->rightChild;// 改变暂存cur  实现衔接
    r->rightChild = cur;           // 根的右子树置为cur
}
// 1. 把LR转换为LL  2. RR型处理
template<class Type>
void AVLtree<Type>::RightRight(TNode<Type> * &r)
{
    TNode<Type> *cur = r;          // cur暂存r
    r = r->rightChild;             // 改变r就是改变根
    cur->rightChild = r->leftChild;// 改变暂存cur  实现衔接
    r->leftChild = cur;            // 根的左子树置为cur
}
// 左平衡处理过程
template<class Type>
void AVLtree<Type>::LeftBalance(TNode<Type> *&r, bool &action)
{
    TNode<Type> *leftsub = r->leftChild;
    TNode<Type> *rightsub = leftsub->rightChild;
    switch (leftsub->balance)
    {
        case 1:// LL型
            leftsub->balance = 0;
            r->balance = 0;
            LeftLeft(r);
            action = false;
            break;
        case 0:
            action = false;
            break;
        case -1:// LR型
            switch (rightsub->balance)
            {
            case 0:// LR型
                r->balance = 0;
                rightsub->balance = 0;
                leftsub->balance = 0;
                break;
            case -1:// LRR型
                r->balance = 0;
                rightsub->balance = 0;
                leftsub->balance = 1;
                break;
            case 1:// LRL型
                rightsub->balance = 0;
                leftsub->balance = 0;
                r->balance = -1;
                break;
            }
            LeftRight(r);  // LR折线型转换处理
            action = false;
            break;
        }
}
// Insert主函数
template<class Type>
void AVLtree<Type>::Insert(TNode<Type> * & root, const Type &x, bool &action)
{
    if (NULL == root)
    {
        root = new TNode<Type>(x);
        return;
    }
    else if (x > root->data)
    {
        Insert(root->rightChild, x, action);
        if (action) // 右子树插入成功
        {
            switch (root->balance)  // 需要重置根的平衡因子
            {
                case 1: // 表示左子树已经存在,现再插入右子树成功
                    root->balance = 0;  //平衡因子置0
                    break;
                case 0: // 表示之前平衡,现再插入右子树成功
                    root->balance = -1;  //平衡因子置1
                    break;
                case -1: // 表示右子树已经存在,现再插入右子树成功
                    RightBalance(root, action);    //右平衡
                    break;
            }
        }
    }
    else if (x < root->data)
    {
        Insert(root->leftChild, x, action);
        if (action)  // 左子树插入成功
        {
            switch (root->balance)    // 需要重置根的平衡因子
            {
            case 1: // 平衡左子树
                LeftBalance(root, action);
                break;
            case 0:
                root->balance = 1;
                break;
            case -1:
                root->balance = 0;
                action = false;
                break;
            }
        }
    }
    else
        cout << "数据" << x << "重复!" << endl;
}
// 查找当前节点的父节点
template<class Type>
TNode<Type> *AVLtree<Type>::Parent(TNode<Type> *p, TNode<Type> *cur)
{
    if (NULL == p || NULL == cur|| p == cur)
        return NULL;
    if (cur == p->leftChild || cur == p->rightChild)
        return p;

    if (p->data < cur->data)
        return Parent(p->rightChild, cur);
    else
        return Parent(p->leftChild, cur);
}
// 查找当前结点的后继 (先序遍历的后继)
template<class Type>
TNode<Type> *AVLtree<Type>::FindNodeNext(TNode<Type> *cur)
{
    if (NULL == cur) 
        return NULL;
    TNode<Type> *p = cur->rightChild;
    while (p->leftChild != NULL)
    {
        p = p->leftChild;
    }
    return p;
}
//////////////////////////////////////////////////////////////////////
/////////////////////////////////删除节点
template<class Type>
void AVLtree<Type>::DeleTNode(TNode<Type> *&cur, TNode<Type> *par)
{
    if (NULL == cur)   
        return;
    //    情况一:删除的是根节点,那么它的父节点必定为NULL
    if (NULL == par)
    {    // cur可能是根结点,并且树仅仅只有一个根
        if (NULL == cur->rightChild && NULL == cur->leftChild)
        {
            delete cur;
            cur = NULL;
            return;
        }
        // 单分支的树
        if (NULL == cur->rightChild)
        {    // 右子树不存在
            TNode<Type> *p = cur;
            cur = cur->leftChild;
            delete p;
            p = NULL;
            return;
        }
        if (NULL == cur->leftChild)
        {    // 左子树不存在
            TNode<Type> *q = cur;
            cur = cur->rightChild;
            delete q;
            q = NULL;
            return;
        }
    }
    // 情况二:删除的属于双分支的节点
    if (cur->leftChild != NULL && cur->rightChild != NULL)
    {
        TNode<Type> *p = FindNodeNext(cur); // 锁定先序遍历的后继
        // 情况一:
        if (cur->rightChild == p)
        {    // 说明右子树仅仅只有一个节点
            cur->balance += 1;    // 删除之后平衡因子改变
            cur->data = p->data;  // 填充数据,意味着改变删除对象
            cur->rightChild = p->rightChild; // 衔接数据
            delete p;  //删除节点p
            p = NULL;
            return;
        }
        // 情况二:
        // 否则
        TNode<Type> *q = Parent(p); // 找到父节点
        if (q->balance != 0)  // 不等于0,说明删除后会影响根结点的平衡因子
          cur->balance += 1;    // 调整根节点的平衡因子
        // 否则
        q->balance -= 1;   // 删除的是左节点,所以加一
        cur->data = p->data; // 填充数据,意味着改变删除对象
        
        q->leftChild = p->rightChild; // 衔接数据

        // 最后才可以动手删除节点  删除节点  释放内存
        delete p;
        p = NULL;
        return;
    }
    // 情况三:单分支(其中包括了叶子节点的情况)
    if (NULL == cur->leftChild)
    {
        TNode<Type> *p = cur;
        if (cur == par->leftChild)
            par->leftChild = cur->rightChild;  // 衔接数据
        else 
            par->rightChild = cur->rightChild; // 衔接数据

        delete p;
        p = NULL;
        return;
    }
    if (NULL == cur->rightChild)
    {
        TNode<Type> *q = cur; 
        if (cur == par->leftChild)
            par->leftChild = cur->leftChild;
        else 
            par->rightChild = cur->leftChild;

        delete q;
        q = NULL;
        return;
    }
}
// 删除过程的主函数
template<class Type>
void AVLtree<Type>::Remove(TNode<Type> * &r, const Type &x, bool &action)
{
    if (NULL == r)    
        return;
    if (x == r->data)
    {
        TNode<Type> *cur = r; // 确定数据的节点信息
        TNode<Type> *par = Parent(r);// 确定当前结点的父节点
        DeleTNode(r, par); // 删除当前指针
        return;
    }
    else if (x > r->data)
    {    // 右边查找
        Remove(r->rightChild, x, action);
        if (action)
        {
            switch (r->balance)
            {
            case -1: // 若原来为1,现在删除了右节点,应该为0
                r->balance = 0;
                break;
                //若原来为-1,现在又再右枝上删除了节点,  
                //树一定不平衡,需要左平衡调整
            case 1:   
                LeftBalance(r, action);
                action = false;
                break;
            case 0: // 若原来为0,现在删除了右节点,应该为-1
                r->balance = 1;
                action = false;
                break;
            }
        }
    }
    else if (x < r->data)
    {
        Remove(r->leftChild, x, action);
        if (action)
        {
            switch (r->balance)
            {
            case -1:// 若原来为1,现在又再左枝上删除了节点,
                    // 树一定不平衡,需要右平衡调整
                RightBalance(r, action);
                break;
            case 1:// 若原来为-1,现在删除了左节点,应该为0
                r->balance = 0;
                break;
            case 0:// 若原来为0,现在删除了左节点,应该为1
                r->balance = -1;
                action = false;
                break;
            }
        }
    }
}

template<class Type>
AVLtree<Type>::AVLtree(): root(NULL)
{}
template<class Type>
void AVLtree<Type>::Insert(const Type &bt)
{
    bool action = true;
    Insert(root, bt, action);
}
template<class Type>
TNode<Type> *AVLtree<Type>::Parent(TNode<Type> *cur)
{
    return Parent(root, cur);
}
template<class Type>
void AVLtree<Type>::Remove(const Type &x)
{
    bool action = true;
    Remove(root, x, action);
}
template<class Type>
void AVLtree<Type>::InOrder(TNode<Type> *p)
{
    if (p != NULL)
    {
        InOrder(p->leftChild);
        cout << p->data << " ";
        InOrder(p->rightChild);
    }
}
template<class Type>
void AVLtree<Type>::InOrder()
{
    InOrder(root);
    cout << endl;
}

 

平衡二叉树AVL树的实现(c++STL)

标签:col   锁定   logs   null   child   clu   ==   平衡   重置   

原文地址:http://www.cnblogs.com/enyala/p/7705607.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!