平衡二叉树

You  should start your program by  initializing an empty AVL  tree.  Your  program takes one line as   input as a command line argument. The input line contains n “modification moves” separated by spaces (1 ≤ n ≤ 100). The available modification moves are

Aint (Character A followed by an int value between 1 and 100): A3 means insert value 3 into the AVL tree.  If 3 is already in the tree, do nothing.

Dint (Character D followed by an int value between 1 and 100): D3 means delete value 3 from the AVL tree.  If 3 is not in the tree, do nothing.

Your input is then followed by exactly one finishing move (PRE or POST or IN): If the finishing move is PRE, then you should print out the tree (in its current situation) in pre-order.  If the tree is empty,  print out      EMPTY. Otherwise, print out the values separated by spaces.  POST and IN are handled  similarly.

You don’t need to worry about invalid inputs.  We wil be executing your code as follows:

Sample input 1: A1 A2 A3 IN Sample  output  1:  1  2   3

Sample input 2: A1 A2 A3 PRE Sample  output  2:  2  1   3

Sample input 3: A1 D1 POST Sample output 3:  EMPTY

 

#include <iostream>
#include<algorithm> 

using namespace std;

/*
* 二叉树的二叉链表存储结构。
* 额外添加树的高度,以判断结点的平衡度。
*/
typedef struct AVLNode
{
    int data;
    struct AVLNode *lchild;
    struct AVLNode *rchild;
    int height;
}AVLNode, *BiTree;

/*
* 获得树高
*/
int GetHeight(BiTree T)
{
    if (T)
        return T->height;
    return 0;
}

/*
* 当T的左子树的左子树上的节点使得T的平衡度为2时,以T为中心进行右旋。
*/
bool LLRotate(BiTree *T)
{
    BiTree lc;
    lc = (*T)->lchild;
    (*T)->lchild = lc->rchild;
    lc->rchild = (*T);

    (*T)->height = max(GetHeight((*T)->lchild), GetHeight((*T)->rchild)) + 1;
    lc->height = max(GetHeight(lc->lchild), GetHeight(lc->rchild)) + 1;

    *T = lc;
    return true;
}
/*
* 当T的右子树的右子树上的节点使得T的平衡度为-2时,以T为中心进行左旋。
*/
bool RRRotate(BiTree *T)
{
    BiTree rc;
    rc = (*T)->rchild;
    (*T)->rchild = rc->lchild;
    rc->lchild = (*T);

    //注意要更新结点的高度。整个树中只有*T的左子树和lc的右子树发生了变化,所以只需更改这两棵树的高度。
    (*T)->height = max(GetHeight((*T)->lchild), GetHeight((*T)->rchild)) + 1;
    rc->height = max(GetHeight(rc->lchild), GetHeight(rc->rchild)) + 1;

    *T = rc;
    return true;
}
/*
* 当T的左子树的右子树上的节点使得T的平衡度为2时,
* 先以T的左子树为中心进行左旋,再以T为中心进行右旋。
*/
bool LRRotate(BiTree *T)
{
    
    BiTree rc;
    rc = (*T)->lchild;
    (*T)->lchild = rc->rchild;//(1)(2)
    rc->rchild = (*T)->lchild->lchild;//(3)(4)
    (*T)->lchild->lchild = rc; //(5)(6)


    rc = (*T)->lchild;
    (*T)->lchild = rc->rchild;
    rc->rchild = (*T);
    (*T) = rc;

    (*T)->lchild->height = max(GetHeight((*T)->lchild->lchild), GetHeight((*T)->lchild->rchild)) + 1;
    (*T)->rchild->height = max(GetHeight((*T)->rchild->lchild), GetHeight((*T)->rchild->rchild)) + 1;
    (*T)->height = max((*T)->lchild->height, (*T)->rchild->height) + 1;
    return true;
}

/*
* 当T的右子树的左子树上的节点使得T的平衡度为-2时,
* 先以T的右子树为中心进行右旋,再以T为中心进行左旋。
*/
bool RLRotate(BiTree *T)
{
    BiTree rc;
    rc = (*T)->rchild;
    (*T)->rchild = rc->lchild;//(1)(2)
    rc->lchild = rc->lchild->rchild;//(3)(4)
    (*T)->rchild->rchild = rc;//(5)(6)

    rc = (*T)->rchild;
    (*T)->rchild = rc->lchild;
    rc->lchild = (*T);
    (*T) = rc;


    (*T)->lchild->height = max(GetHeight((*T)->lchild->lchild), GetHeight((*T)->lchild->rchild)) + 1;
    (*T)->rchild->height = max(GetHeight((*T)->rchild->lchild), GetHeight((*T)->rchild->rchild)) + 1;
    (*T)->height = max((*T)->lchild->height, (*T)->rchild->height) + 1;

    return true;
}


/*
* 插入操作。
* 如果以*T为根结点的二叉平衡树中已有结点key,插入失败,函数返回FALSE;
* 否则将结点key插入到树中,插入结点后的树仍然为二叉平衡树,函数返回TRUE。
*/
bool AVLInsert(BiTree *T, int key)
{
    BiTree t;

    //如果当前查找的根结点为空树,表明查无此结点,故插入结点。
    if (!*T)
    {
        t = (BiTree)malloc(sizeof(AVLNode));
        t->data = key;
        t->height = 1;
        t->lchild = NULL;
        t->rchild = NULL;
        *T = t;
        return true;
    }
    //已有此结点,不再插入。
    else if (key == (*T)->data)
    {
        return false;
    }
    //在左子树中递归插入。
    else if (key < (*T)->data)
    {
        if (!AVLInsert(&((*T)->lchild), key))
            return false;
        else
        {
            //已在*T的左子树插入结点key,判断是否需要进行旋转以保持二叉平衡树的特性。
            if (2 == GetHeight((*T)->lchild) - GetHeight((*T)->rchild))
            {
                //在左子树的左子树中插入结点。
                if (GetHeight((*T)->lchild->lchild) > GetHeight((*T)->lchild->rchild))
                {
                    LLRotate(T);
                }
                //在左子树的右子树中插入结点。
                else
                {
                    LRRotate(T);
                }
            }
            //插入成功,修改树的高度。
            (*T)->height = std::max(GetHeight((*T)->lchild), GetHeight((*T)->rchild)) + 1;
            return true;
        }
    }
    //在右子树中递归插入。
    else // (key > (*T)->data)
    {
        if (!AVLInsert(&(*T)->rchild, key))
            return false;
        else
        {
            //已在*T的右子树插入结点key,判断是否需要进行旋转以保持二叉平衡树的特性。
            if (-2 == GetHeight((*T)->lchild) - GetHeight((*T)->rchild))
            {
                if (GetHeight((*T)->rchild->lchild) > GetHeight((*T)->rchild->rchild))
                {
                    
                    RLRotate(T);
                }
                else
                {
                    RRRotate(T);
                }
            }
            //插入成功,修改树的高度。
            (*T)->height = max(GetHeight((*T)->lchild), GetHeight((*T)->rchild)) + 1;
            return true;
        }
    }
}

/*
* 删除操作。
* 如果以*T为根结点的树中存在结点key,将结点删除,函数返回TRUE,
* 否则删除失败,函数返回FALSE。
*/
bool AVLDelete(BiTree *T, int key)
{
    BiTree pre, post;

    //没有找到该结点。
    if (!*T)
        return false;
    //找到结点,将它删除。
    else if (key == (*T)->data)
    {
        //待删除节点为叶子结点。
        if (!(*T)->lchild && !(*T)->rchild)
            *T = NULL;
        //待删除结点只有右孩子。
        else if (!(*T)->lchild )
            *T = (*T)->rchild;
        //待删除结点只有左孩子。
        else if (!(*T)->rchild)
            *T = (*T)->lchild;
        //待删除结点既有左孩子,又有右孩子。
        else
        {
            //当待删除结点*T左子树的高度大于右子树的高度时,用*T的前驱结点pre代替*T,
            //再将结点pre从树中删除。这样可以保证删除结点后的树仍为二叉平衡树。
            if (GetHeight((*T)->lchild) > GetHeight((*T)->rchild))
            {
                //寻找前驱结点pre。
                pre = (*T)->lchild;
                while (pre->rchild)
                {
                    pre = pre->rchild;
                }
                //用pre替换*T。
                (*T)->data = pre->data;

                //删除节点pre。
                //虽然能够确定pre所属最小子树的根结点为&pre,
                //但是不采用AVLDelete(&pre,pre->data)删除pre,目的是方便递归更改节点的高度。
                AVLDelete(&((*T)->lchild), pre->data);
            }
            //当待删除结点*T左子树的高度小于或者等于右子树的高度时,用*T的后继结点post代替*T,
            //再将结点post从树中删除。这样可以保证删除结点后的树仍为二叉平衡树。
            else
            {
                //寻找后继节点post。
                post = (*T)->rchild;
                while (post->lchild)
                    post = post->lchild;
                //用post替换*T。
                (*T)->data = post->data;

                //删除节点post。
                //虽然能够确定post所属最小子树的根结点为&post,
                //但是不采用AVLDelete(&post,post->data)删除post,目的是方便递归更改节点的高度。
                AVLDelete(&((*T)->rchild), post->data);
            }
        }
        return true;
    }
    //在左子树中递归删除。
    else if (key < (*T)->data)
    {
        if (!AVLDelete(&((*T)->lchild), key))
            return false;
        else
        {
            //删除成功,修改树的高度。
            (*T)->height = max(GetHeight((*T)->lchild), GetHeight((*T)->rchild)) + 1;
            if (2 == GetHeight((*T)->lchild) - GetHeight((*T)->rchild))//左子树高
            {
                if (GetHeight((*T)->lchild->lchild) >= GetHeight((*T)->lchild->rchild))//LL
                {
                    LLRotate(T);
                }
                else//LR
                {
                    LRRotate(T);
                }
            }
            else if (-2 == GetHeight((*T)->lchild) - GetHeight((*T)->rchild))//右子树高
            {
                if (GetHeight((*T)->rchild->rchild) >= GetHeight((*T)->rchild->lchild))//RR
                {
                    RRRotate(T);
                }
                else//RL
                {
                    RLRotate(T);
                }
            }
            
            return true;
        }
    }
    //在右子树中递归删除。
    else
    {
        if (!AVLDelete(&((*T)->rchild), key))
            return false;
        else
        {
            //删除成功,修改树的高度。
            (*T)->height = max(GetHeight((*T)->lchild), GetHeight((*T)->rchild)) + 1;
            if (2 == GetHeight((*T)->lchild) - GetHeight((*T)->rchild))//左子树高
            {        
                if (GetHeight((*T)->lchild->lchild) >= GetHeight((*T)->lchild->rchild))//LL
                {
                    LLRotate(T);
                }
                else//LR
                {
                    LRRotate(T);
                }
            }
            else if (-2 == GetHeight((*T)->lchild) - GetHeight((*T)->rchild))//右子树高
            {
                if (GetHeight((*T)->rchild->rchild) >= GetHeight((*T)->rchild->lchild))//RR
                {
                    RRRotate(T);
                }
                else//RL
                {
                    RLRotate(T);
                }
            }
            return true;
        }
    }
}

int getNumber(char *src, int len)
{
    int ret = 0;
    int num = 1;
    for (int i = len - 1; i > 0; i--)
    {
        ret += (src[i] - 48) * num;
        num *= 10;
    }
    return ret;
}

/*
* 中序遍历输出树结构。
*/
bool InOrderTraverse(BiTree T)
{
    if (T)
    {
        InOrderTraverse(T->lchild);
        cout << T->data << " ";
        InOrderTraverse(T->rchild);
    }
    return true;
}
/*
* 先序遍历输出树结构。
*/
bool PreOrderTraverse(BiTree T)
{
    if (T)
    {
        cout << T->data << " ";
        PreOrderTraverse(T->lchild);
        PreOrderTraverse(T->rchild);
    }
    return true;
}
/*
* 后序遍历输出树结构。
*/
bool PostOrderTraverse(BiTree T)
{
    if (T)
    {
        PostOrderTraverse(T->lchild);
        PostOrderTraverse(T->rchild);
        cout << T->data << " ";
    }
    return true;
}
int main(int argc, char **argv)
{

    BiTree T = NULL;    //注意一定要将T初始化为空树。

    for (int i = 1; i < argc; i++)
    {
        
        /*if (T)
        {
            PreOrderTraverse(T);
            cout << endl;
        }
        else
        {
            cout << "EMPTY" << endl;
        }
        
        if (argv[i][0] == 'D' && argv[i][1] == '5')
        {
            cout << "" << endl;
        }*/
        cout << argv[i] << " ";
        if (argv[i][0] == 'A' || argv[i][0] == 'a')
        {
            AVLInsert(&T, getNumber(argv[i], strlen(argv[i])));
        }
        else if (argv[i][0] == 'D' || argv[i][0] == 'd')
        {
            AVLDelete(&T, getNumber(argv[i], strlen(argv[i])));
        }
        else if (argv[i][0] == 'I')//IN
        {
            cout << endl;
            if (T)
            {
                InOrderTraverse(T);
            }
            else
            {
                cout << "EMPTY" << endl;
            }

        }
        else if (argv[i][0] == 'P' && argv[i][1] == 'R')//PRE
        {
            cout << endl;
            if (T)
            {
                PreOrderTraverse(T);
            }
            else
            {
                cout << "EMPTY" << endl;
            }

        }
        else if (argv[i][0] == 'P' && argv[i][1] == 'O')//POST
        {
            cout << endl;
            if (T)
            {
                PostOrderTraverse(T);
            }
            else
            {
                cout << "EMPTY" << endl;
            }

        }
    }

    system("PAUSE");                    // 调用库函数system()
    return 0;                            // 返回值0, 返回操作系统
}

 

  

posted @ 2018-05-01 19:01  huluBrother  阅读(321)  评论(0)    收藏  举报