二叉查找树(BST)和平衡二叉查找树(AVL)

二叉查找树(BST)

前一篇介绍了树,却未介绍树有什么用。但就算我不说,你也能想得到,看我们Windows的目录结构,其实就是树形的,一个典型的分类应用。当然除了分类,树还有别的作用,我们可以利用树建立一个非常便于查找取值又非常便于插入删除的数据结构,这就是马上要提到的二叉查找树(Binary Search Tree),这种二叉树有个特点:对任意节点而言,左子(当然了,存在的话)的值总是小于本身,而右子(存在的话)的值总是大于本身。

这种特性使得我们要查找其中的某个值都很容易,从根开始,小的往左找,大的往右找,不大不小的就是这个节点了;插入一样的道理,从根开始,小的往左,大的往右,直到叶子,就插入,算法比较简单,不一一列了,它们的时间复杂度期望为Ο(logn)。(为什么是“期望”,后面会讲)

删除则稍微麻烦点,因为我们删的不一定是叶子,如果只是叶子,那就好办,如果不是呢?我们最通常的做法就是把这个节点往下挪,直到它变为叶子为止,看图。


也许你要问,如果和左子树最大节点交换后,要删除的节点依然不是叶子,那怎么办呢?那继续呗,看图:

那左子树不存在的情况下呢?你可以查找右子树的最小节点,和上面是类似的,图我就不画了。

平衡二叉查找树(AVL)

前面说了,二叉查找树方便查找取值插入删除,其复杂度不过为Ο(logn),但这是个“期望值”,因为我们也有比较差的情况,比如下面这棵树:

说是树,其实已经退化为链表了,但从概念上来说它依然是一棵二叉查找树,这棵树怎么形成的呢?很简单,我们只要按着1,2,3,4,5,6,7这样的顺序往一个空的二叉查找树里添加元素,就形成了。这样我们再添加8,9,10……那真的就变成了一个链表结构,那插入的复杂度也就变成了Ο(n)。导致这种糟糕的原因是这棵树非常不平衡,右树的重量远大于左树,所以我们提出了一种叫“平衡二叉查找树”的结构,平衡二叉查找树英文叫AVL,而不是我本来以为的什么Balance BST,AVL来自于人名,我这里就不追究了。

平衡,顾名思义,就是两边看起来比较对称,但很多时候我们是做不到绝对的对称(绝对对称即对任意子树而言,左右节点的数量都相等),因为只有(2^n-1)元素数目的二叉树才能做到绝对对称,所以我们使用了“高度”(height)这么个概念,某节点的高度指的是它离它的子树的叶子的最远距离:


那么我再引申出两个概念,左高和右高:
左高 = 左节点空 ? 0 : (左节点高+1)
右高 = 右节点空 ? 0 : (右节点高+1)

那我们就可以给AVL下个定义了,对AVL的任意节点而言:

ABS(左高 - 右高) <= 1

做到了这点,这棵树看起来就比较平衡了,如何生成一棵AVL树呢?算法十分不简单,那我们先通过图来获得一些最直观的认识,就先按1,2,3,4……这样的自然数顺序加入到树中,下图体现出了树的构造变化:

随着新节点的加入,树自动调整自身结构,达到新的平衡状态,这就是我们想要的AVL树。我们先要分析,为什么树会失衡?是由于插入了一个元素,对吧,那我们能不能把不同的插入情况全部概括起来并作出统一的调整来使得树重新平衡?答案是肯定的,也有人帮我们研究好了,只是证明这个过程需要一些数学功底,我是不行的了,所以直接给出算法示意图和范例。

LL型调整:


再给一个LL型调整的实例:

RR型调整,其实就是LL型调整的镜像而已:


这是一个RR型调整的实例:

接下去就是LR型调整:

这是一个LR型调整的实例:

RL型调整是LR型调整的镜像,所以不再画图了。

至于如何选择不同的调整类型,我后面将给出代码,看“DoBalance”这个函数的实现,很清晰的。那接下去我们还要面临一个比较困难的问题,就是删除及删除平衡,因为不光是插入元素可能导致不平衡,删除也会。不过我们都有个同样的前提,就是无论是插入前还是删除前的二叉树,都是平衡的。

我参考的书上说删除和插入其实是很类似的,具体实现却没说,我后来写代码蛮辛苦的,最后发现确实差别不大,但在调整相关节点高度的时候确实有点细微上的差别,这个在我的代码里也能看得出来。下面我就给出我的代码,我已经通过了初步的测试,不过也许代码还有bug,如果发现了,请留言。

代码比较长,其中还利用了之前的堆栈和队列结构,可以算是复习,如果觉得代码晦涩难懂,也可以跳过,有些怕自己的代码写得不够好……

另附带一些代码说明:
1,TreeNode目前只带一个“数据”,就是iData,所以交换节点位置时候,为了方便,只需要交换这个数据;
2,代码中的pMinBST指向的是“最小不平衡树”,即:从插入或删除的位置开始往上查找出现的第一个不平衡的节点;
3,“往上查找”就需要借助一个Stack结构;
4,AVL树的析构采用了后序遍历,由于是析构,之后不再用到,所以后序遍历时候改变了节点指针的值,后续遍历使用了Queue结构;
5,删除节点时候,寻找并交换叶子节点的操作有些晦涩,往左寻找最大节点,为什么找到了最大并交换,而它还不是叶子的时候,我只需要再往左找并交换一次就可以了呢?因为我删除到时候有个前提:这棵树是平衡的,往右寻找最小节点的道理跟这个一样的;
6,有什么问题请留言。

#include  " stdio.h "

//  TreeNode
//
struct  TreeNode
{
    TreeNode(
int  iVal);
    
int  UpdateHeight();
    
int  GetLeftHeight();
    
int  GetRightHeight();
    
int  GetDiff();  // Left Height - Right height

    
int  iData;

    
int  iHeight;
    TreeNode
*  pLeft;
    TreeNode
*  pRight;
};

TreeNode::TreeNode(
int  iVal)
{
    iData 
=  iVal;
    iHeight 
=   0 ;
    pLeft 
=   0 ;
    pRight 
=   0 ;
}

int  TreeNode::UpdateHeight()
{
    
int  iHeightLeft  =  GetLeftHeight();
    
int  iHeightRight  =  GetRightHeight();
    
if (iHeightLeft == 0   &&  iHeightRight == 0 )
        iHeight 
=   0 ;
    
else
        iHeight 
=  (iHeightLeft > iHeightRight) ? (iHeightLeft):(iHeightRight);
    
return  iHeight;
}

int  TreeNode::GetLeftHeight()
{
    
if (pLeft != 0 )
        
return  pLeft -> iHeight  +   1 ;
    
else
        
return   0 ;
}

int  TreeNode::GetRightHeight()
{
    
if (pRight != 0 )
        
return  pRight -> iHeight  +   1 ;
    
else
        
return   0 ;
}

int  TreeNode::GetDiff()
{
    
int  iHeightLeft  =   0 ;
    
int  iHeightRight  =   0 ;
    
    
if (pLeft != 0 )
        iHeightLeft 
=  pLeft -> iHeight  +   1 ;
    
if (pRight != 0 )
        iHeightRight 
=  pRight -> iHeight  +   1 ;

    
return  iHeightLeft  -  iHeightRight;
}

//  Stack
//
class  Stack
{
public :
    Stack(
int  iAmount  =   10 );
    
~ Stack();
    
    
// return 1 means succeeded, 0 means failed.
     int  Pop(TreeNode *   &  val);
    
int  Push(TreeNode *  val);
    
int  Top(TreeNode *   &  val);

    
// iterator
     int  GetTop(TreeNode *   & val);
    
int  GetNext(TreeNode *   & val);
private :
    TreeNode
**  m_pData;
    
int  m_iCount;
    
int  m_iAmount;

    
// iterator
     int  m_iCurr;
};

Stack::Stack(
int  iAmount)
{
    m_pData 
=   new  TreeNode * [iAmount];
    m_iCount 
=   0 ;
    m_iAmount 
=  iAmount;
    m_iCurr 
=   0 ;
}

Stack::
~ Stack()
{
    delete m_pData;
}

int  Stack::Pop(TreeNode *   &  val)
{
    
if (m_iCount > 0 )
    {
        
-- m_iCount;
        val 
=  m_pData[m_iCount];
        
return   1 ;
    }
    
return   0 ;
}

int  Stack::Push(TreeNode *  val)
{
    
if (m_iCount < m_iAmount)
    {
        m_pData[m_iCount] 
=  val;
        
++ m_iCount;
        
return   1 ;
    }
    
return   0 ;
}

int  Stack::Top(TreeNode *   &  val)
{
    
if (m_iCount > 0   &&  m_iCount <= m_iAmount)
    {
        val 
=  m_pData[m_iCount - 1 ];
        
return   1 ;
    }
    
return   0 ;
}

int  Stack::GetTop(TreeNode *   & val)
{
    
if (m_iCount > 0   &&  m_iCount <= m_iAmount)
    {
        val 
=  m_pData[m_iCount - 1 ];
        m_iCurr 
=  m_iCount  -   1 ;
        
return   1 ;
    }
    
return   0 ;
}

int  Stack::GetNext(TreeNode *   & val)
{
    
if ((m_iCurr - 1 ) < (m_iCount - 1 &&  (m_iCurr - 1 ) >= 0 )
    {
        
-- m_iCurr;
        val 
=  m_pData[m_iCurr];
        
return   1 ;
    }
    
return   0 ;
}

//  The Queue
//
class  Queue
{
public :
    Queue(
int  iAmount = 10 );
    
~ Queue();
    
    
// return 0 means failed, return 1 means succeeded.
     int  Enqueue(TreeNode *  node);
    
int  Dequeue(TreeNode *   &  node);
private :
    
int  m_iAmount;
    
int  m_iCount;
    TreeNode
**  m_ppFixed;  // The pointer array to implement the queue.
    
    
int  m_iHead;
    
int  m_iTail;
};

Queue::Queue(
int  iAmount)
{
    m_iCount 
=   0 ;
    m_iAmount 
=  iAmount;
    m_ppFixed 
=   new  TreeNode * [iAmount];
    
    m_iHead 
=   0 ;
    m_iTail 
=  iAmount - 1 ;
}

Queue::
~ Queue()
{
    delete[] m_ppFixed;
}

int  Queue::Enqueue(TreeNode *  node)
{
    
if (m_iCount < m_iAmount)
    {
        
++ m_iTail;
        
if (m_iTail  >  m_iAmount - 1 )
            m_iTail 
=   0 ;
        m_ppFixed[m_iTail] 
=  node;
        
++ m_iCount;
        
return   1 ;
    }
    
else
        
return   0 ;
}

int  Queue::Dequeue(TreeNode *   &  node)
{
    
if (m_iCount > 0 )
    {
        node 
=  m_ppFixed[m_iHead];
        
++ m_iHead;
        
if (m_iHead  >  m_iAmount - 1 )
            m_iHead 
=   0 ;
        
-- m_iCount;
        
return   1 ;
    }
    
else
        
return   0 ;
}

//  AVLTree
//
class  CAVLTree
{
public :
    CAVLTree();
    
~ CAVLTree();
    
    TreeNode
*  Insert( int  iVal);
    
int  Delete( int  iVal);
    TreeNode
*  FindNode( int  iVal);  // the find function, returns 0 means not found.
    
#ifdef _DEBUG
    
void  PrintTree();
#endif

protected :
    
// Update the height after insert or delete.
    
// And find the minimum unbalance BST.
     int  UpdateHeight(Stack  & st, TreeNode *   & pMinBST, TreeNode *   & pMinBSTParent,  int &  iLeftRight);

    
// Rotate
     void  DoBalance(TreeNode  * pNode, TreeNode *  pMinBSTParent,  int  iLeftRight);
    
void  LLRotate(TreeNode  * pNode, TreeNode *  pMinBSTParent,  int  iLeftRight);
    
void  RRRotate(TreeNode  * pNode, TreeNode *  pMinBSTParent,  int  iLeftRight);
    
void  LRRotate(TreeNode  * pNode, TreeNode *  pMinBSTParent,  int  iLeftRight,  int  iSpecialFlag = 0 );
    
void  RLRotate(TreeNode  * pNode, TreeNode *  pMinBSTParent,  int  iLeftRight,  int  iSpecialFlag = 0 );
    
    
void  SwapTwoNodes(TreeNode  * pNode1, TreeNode  * pNode2);  // Swap their value only.

    TreeNode 
* m_pRoot;
};

CAVLTree::CAVLTree()
{
    m_pRoot 
=  NULL;
}

CAVLTree::
~ CAVLTree()
{
    Stack st(
40 );  // 2^40 must be enough.

    
// Postorder traverse the tree to release all nodes.
    TreeNode  * pNode  =  m_pRoot;
    TreeNode 
* pTemp;
    
if (pNode == 0 )
        
return ;

    
while  ( 1 )
    {
        
if (pNode -> pLeft != 0 )
        {
            st.Push(pNode);
            pTemp 
=  pNode;
            pNode 
=  pNode -> pLeft;
            pTemp
-> pLeft  =   0 ;
            
continue ;
        }
        
        
if (pNode -> pRight != 0 )
        {
            st.Push(pNode);
            pTemp 
=  pNode;
            pNode 
=  pNode -> pRight;
            pTemp
-> pRight  =   0 ;
            
continue ;
        }
        
        delete pNode;

        
if ( 0 == st.Pop(pNode))
            
break ;
    }
}

TreeNode
*  CAVLTree::Insert( int  iVal)
{
    Stack st(
40 );  // To record the path.
    TreeNode  * pNode  =  m_pRoot;
    TreeNode 
* pIns;
    
int  iLeftOrRight;  //  0 means left, 1 means right.
     while  ( 1 )
    {
        
if (pNode == 0 // Insert at this position
        {
            TreeNode 
* pNew  =   new  TreeNode(iVal);
            TreeNode 
* pPrev;
            
if ( 0 != st.Top(pPrev))
            {
                
if ( 0 == iLeftOrRight)
                    pPrev
-> pLeft  =  pNew;
                
else
                    pPrev
-> pRight  =  pNew;
            }
            
else   // The root
            {
                m_pRoot 
=  pNew;
                
return  m_pRoot;
            }

            pIns 
=  pNew;
            
if ( 0 == iLeftOrRight  &&  pPrev -> pRight != 0   ||   1 == iLeftOrRight  &&  pPrev -> pLeft != 0 // Need not to change.
                 return  pIns;

            
break ;
        }

        
if (iVal < pNode -> iData)
        {
            st.Push(pNode);
            pNode 
=  pNode -> pLeft;
            iLeftOrRight 
=   0 ;
        }
        
else   if (iVal > pNode -> iData)
        {
            st.Push(pNode);
            pNode 
=  pNode -> pRight;
            iLeftOrRight 
=   1 ;
        }
        
else
            
return  pNode;
    }

    TreeNode
*  pMinBST;
    TreeNode
*  pMinBSTParent;
    
int  iLRParent;
    UpdateHeight(st, pMinBST, pMinBSTParent, iLRParent);
    
if (pMinBST != 0 // It exists. need balance.
    {
        DoBalance(pMinBST, pMinBSTParent, iLRParent);
    }
    
return  pIns;
}

// Update the height after insert or delete.
int  CAVLTree::UpdateHeight(Stack  & st, TreeNode *   & pMinBST, TreeNode *   & pMinBSTParent,  int &  iLRParent)
{
    TreeNode 
* pNode;
    pMinBST 
=   0 ;
    pMinBSTParent 
=   0 ;

    
if ( 0 == st.GetTop(pNode))
        
return   0 ;
    
    
while ( 1 )
    {
        pNode
-> UpdateHeight();
        
int  iDiff  =  pNode -> GetDiff();
        
if (iDiff > 1   ||  iDiff <- 1 // unbalance
        {
            pMinBST 
=  pNode;
            
if ( 0 != st.GetNext(pMinBSTParent))
            {
                
if (pMinBSTParent -> pLeft == pMinBST)
                    iLRParent 
=   0 // left
                 else
                    iLRParent 
=   1 // right
            }
            
return   0 ;
        }

        
if ( 0 == st.GetNext(pNode))
            
break ;
    }

    
return   0 ;
}

void  CAVLTree::DoBalance(TreeNode  * pNode, TreeNode *  pMinBSTParent,  int  iLeftRight)
{
    
if (pNode -> GetLeftHeight()  <  pNode -> GetRightHeight())
    {
        
if (pNode -> pRight -> GetLeftHeight()  <  pNode -> pRight -> GetRightHeight())
            RRRotate(pNode, pMinBSTParent, iLeftRight);
        
else   if (pNode -> pRight -> GetLeftHeight()  >  pNode -> pRight -> GetRightHeight())
            RLRotate(pNode, pMinBSTParent, iLeftRight);
        
else
            RLRotate(pNode, pMinBSTParent, iLeftRight, 
1 );
    }
    
else
    {
        
if (pNode -> pLeft -> GetLeftHeight()  >  pNode -> pLeft -> GetRightHeight())
            LLRotate(pNode, pMinBSTParent, iLeftRight);
        
else   if (pNode -> pLeft -> GetLeftHeight()  <  pNode -> pLeft -> GetRightHeight())
            LRRotate(pNode, pMinBSTParent, iLeftRight);
        
else
            LRRotate(pNode, pMinBSTParent, iLeftRight, 
1 );
    }
}

//       B               A
//      / \             / \
//     A   BR    =>    AL  B
//    / \              +  / \
//   AL  AR              AR  BR
//   +
void  CAVLTree::LLRotate(TreeNode  * pNode, TreeNode *  pMinBSTParent,  int  iLeftRight)
{
    
// B, A and AL must be exist. BR and AR may be null.
    TreeNode  * pNodeB  =  pNode;
    TreeNode 
* pNodeA  =  pNodeB -> pLeft;
    TreeNode 
* pNodeAR  =  pNodeA -> pRight;
    pNodeA
-> pRight  =  pNodeB;
    pNodeB
-> pLeft  =  pNodeAR;

    
// Handle the height
    pNodeB -> iHeight  -=   2 ;

    
if (pMinBSTParent == 0 // root
        m_pRoot  =  pNodeA;
    
else
    {
        
if (iLeftRight == 0 // left
            pMinBSTParent -> pLeft  =  pNodeA;
        
else
            pMinBSTParent
-> pRight  =  pNodeA;
    }
}

//       A                B
//      / \              / \
//     AL  B      =>    A   BR
//        / \          / \  +
//       BL  BR       AL  BL
//           +
void  CAVLTree::RRRotate(TreeNode  * pNode, TreeNode *  pMinBSTParent,  int  iLeftRight)
{
    TreeNode 
* pNodeA  =  pNode;
    TreeNode 
* pNodeB  =  pNodeA -> pRight;
    TreeNode 
* pNodeBL  =  pNodeB -> pLeft;
    pNodeB
-> pLeft  =  pNodeA;
    pNodeA
-> pRight  =  pNodeBL;

    
// Handle the height
    pNodeA -> iHeight  -=   2 ;

    
if (pMinBSTParent == 0 // root
        m_pRoot  =  pNodeB;
    
else
    {
        
if (iLeftRight == 0 // left
            pMinBSTParent -> pLeft  =  pNodeB;
        
else
            pMinBSTParent
-> pRight  =  pNodeB;
    }
}

//           C                   B
//          / \                /   \
//         A   CR             A     C
//        / \         =>     / \   / \
//       AL  B              AL BL BR CR
//          / \                   +
//         BL  BR
//             +
//  Special flag is used for some kind of delete operation, for example:
//         4                   3
//        / \                 / \
//       2   5(-)    =>      2   4
//      / \                 /
//     1   3               1
void  CAVLTree::LRRotate(TreeNode  * pNode, TreeNode *  pMinBSTParent,  int  iLeftRight,  int  iSpecialFlag)
{
    TreeNode 
* pNodeC  =  pNode;
    TreeNode 
* pNodeA  =  pNodeC -> pLeft;
    TreeNode 
* pNodeB  =  pNodeA -> pRight;
    TreeNode 
* pNodeBL  =  pNodeB -> pLeft;
    TreeNode 
* pNodeBR  =  pNodeB -> pRight;
    pNodeB
-> pLeft  =  pNodeA;
    pNodeB
-> pRight  =  pNodeC;
    pNodeA
-> pRight  =  pNodeBL;
    pNodeC
-> pLeft  =  pNodeBR;

    
// Handle the height
     if (iSpecialFlag == 0 )
    {
        pNodeA
-> iHeight  -=   1 ;
        pNodeB
-> iHeight  +=   1 ;
    }
    
else
    {
        pNodeB
-> iHeight  +=   2 ;
    }
    pNodeC
-> iHeight  -=   2 ;

    
if (pMinBSTParent == 0 // root
        m_pRoot  =  pNodeB;
    
else
    {
        
if (iLeftRight == 0 // left
            pMinBSTParent -> pLeft  =  pNodeB;
        
else
            pMinBSTParent
-> pRight  =  pNodeB;
    }
}

//           B                   A
//          / \                /   \
//         BL  C              B     C
//            / \      =>    / \   / \
//           A   CR         BL AL AR CR
//          / \                   +
//         AL  AR
//             +
//  Special flag is used for some kind of delete operation, for example:
//         3                   4
//        / \                 / \
//    (-)2   5      =>       3   5
//          / \                   \
//         4   6                   6
void  CAVLTree::RLRotate(TreeNode  * pNode, TreeNode *  pMinBSTParent,  int  iLeftRight,  int  iSpecialFlag)
{
    TreeNode 
* pNodeB  =  pNode;
    TreeNode 
* pNodeC  =  pNodeB -> pRight;
    TreeNode 
* pNodeA  =  pNodeC -> pLeft;
    TreeNode 
* pNodeAL  =  pNodeA -> pLeft;
    TreeNode 
* pNodeAR  =  pNodeA -> pRight;
    pNodeA
-> pLeft  =  pNodeB;
    pNodeA
-> pRight  =  pNodeC;
    pNodeC
-> pLeft  =  pNodeAR;
    pNodeB
-> pRight  =  pNodeAL;

    
// Handle the height
     if (iSpecialFlag == 0 )
    {
        pNodeC
-> iHeight  -=   1 ;
        pNodeA
-> iHeight  +=   1 ;
    }
    
else
    {
        pNodeA
-> iHeight  +=   2 ;
    }
    pNodeB
-> iHeight  -=   2 ;
    
    
if (pMinBSTParent == 0 // root
        m_pRoot  =  pNodeA;
    
else
    {
        
if (iLeftRight == 0 // left
            pMinBSTParent -> pLeft  =  pNodeA;
        
else
            pMinBSTParent
-> pRight  =  pNodeA;
    }
}

int  CAVLTree::Delete( int  iVal)
{
    
if (m_pRoot == 0 )
        
return   0 ;

    Stack st(
40 );  // To record the path.
    TreeNode  * pNode  =  m_pRoot;
    TreeNode 
* pPrev;
    
int  iLeftOrRight;  //  0 means left, 1 means right.

    
while  ( 1 )
    {
        
if (pNode -> iData == iVal)  // Yes, it is.
        {
            st.Push(pNode);
            
break ;
        }

        
if (iVal < pNode -> iData)
        {
            st.Push(pNode);
            
if (pNode -> pLeft != 0 )
                pNode 
=  pNode -> pLeft;
            
else
                
return   0 ;
            iLeftOrRight 
=   0 ;
        }
        
else   // iVal > pNode->iData
        {
            st.Push(pNode);
            
if (pNode -> pRight != 0 )
                pNode 
=  pNode -> pRight;
            
else
                
return   0 ;
            iLeftOrRight 
=   1 ;
        }
    }
    
    
int  iLeafLeftRight;

    
if (pNode -> iHeight == 0 // It is the leaf node.
    {
        
if ( 0 != st.GetTop(pPrev))
        {
            iLeafLeftRight 
=  iLeftOrRight;
        }
        
else   // The root, this tree is going to be null.
        {
            delete m_pRoot;
            m_pRoot 
=   0 ;
            
return   0 ;
        }
    }
    
else   if (pNode -> pLeft != NULL)
    {
        iLeafLeftRight 
=   0 ;
        
// Move this node to the bottom.
        TreeNode  * pBiggestLeft  =  pNode -> pLeft;
        st.Push(pBiggestLeft);
        
while (pBiggestLeft -> pRight != NULL)
        {
            pBiggestLeft 
=  pBiggestLeft -> pRight;
            st.Push(pBiggestLeft);
            iLeafLeftRight 
=   1 ;
        }
        SwapTwoNodes(pBiggestLeft, pNode);
        
if (pBiggestLeft -> pLeft != NULL)
        {
            SwapTwoNodes(pBiggestLeft, pBiggestLeft
-> pLeft);
            st.Push(pBiggestLeft
-> pLeft);
            iLeafLeftRight 
=   0 ;
        }
    }
    
else   // pNode->pRight!=NULL
    {
        iLeafLeftRight 
=   1 ;
        
// Move this node to the bottom.
        TreeNode  * pLeastRight  =  pNode -> pRight;
        st.Push(pLeastRight);
        
while (pLeastRight -> pLeft != NULL)
        {
            pLeastRight 
=  pLeastRight -> pLeft;
            st.Push(pLeastRight);
            iLeafLeftRight 
=   0 ;
        }
        SwapTwoNodes(pLeastRight, pNode);
        
if (pLeastRight -> pRight != NULL)
        {
            SwapTwoNodes(pLeastRight, pLeastRight
-> pRight);
            st.Push(pLeastRight
-> pRight);
            iLeafLeftRight 
=   1 ;
        }
    }

    
// Delete the leaf.
    TreeNode  * pToDel;
    st.Pop(pToDel);
    delete pToDel;
    TreeNode 
* pToChange;
    st.GetTop(pToChange);
    
if (iLeafLeftRight == 0 )
        pToChange
-> pLeft  =   0 ;
    
else
        pToChange
-> pRight  =   0 ;

    TreeNode
*  pMinBST;
    TreeNode
*  pMinBSTParent;
    
int  iLRParent;
    UpdateHeight(st, pMinBST, pMinBSTParent, iLRParent);
    
if (pMinBST != 0 // It exists. need balance.
    {
        DoBalance(pMinBST, pMinBSTParent, iLRParent);
    }

    
return   0 ;
}

TreeNode
*  CAVLTree::FindNode( int  iVal)
{
    TreeNode
*  pNode  =  m_pRoot;
    
while  (pNode != 0 )
    {
        
if (iVal < pNode -> iData)
            pNode 
=  pNode -> pLeft;
        
else   if (iVal > pNode -> iData)
            pNode 
=  pNode -> pRight;
        
else
            
return  pNode;
    }

    
return   0 ;
}

void  CAVLTree::SwapTwoNodes(TreeNode  * pNode1, TreeNode  * pNode2)
{
    
int  iDataTmp  =  pNode1 -> iData;

    pNode1
-> iData  =  pNode2 -> iData;

    pNode2
-> iData  =  iDataTmp;
}

#ifdef _DEBUG

void  CAVLTree::PrintTree()
{
    printf(
" --------------------\n " );
    
if (m_pRoot == 0 )
    {
        printf(
" null tree.\n " );
        
return ;
    }
    Queue que(
100 );
    que.Enqueue(m_pRoot);
    TreeNode
*  pNode;
    
while  ( 0 != que.Dequeue(pNode))
    {
        
if (pNode -> pLeft != 0   &&  pNode -> pRight != 0 )
        {
            printf(
" %d(%d) -> %d %d\n " , pNode -> iData, pNode -> iHeight, pNode -> pLeft -> iData, pNode -> pRight -> iData);
            que.Enqueue(pNode
-> pLeft);
            que.Enqueue(pNode
-> pRight);
        }
        
else   if (pNode -> pLeft != 0 )
        {
            que.Enqueue(pNode
-> pLeft);
            printf(
" %d(%d) -> %d x\n " , pNode -> iData, pNode -> iHeight, pNode -> pLeft -> iData);
        }
        
else   if (pNode -> pRight != 0 )
        {
            que.Enqueue(pNode
-> pRight);
            printf(
" %d(%d) -> x %d\n " , pNode -> iData, pNode -> iHeight, pNode -> pRight -> iData);
        }
    }
}

#endif

//  Main
//
int  main( int  argc,  char *  argv[])
{
    CAVLTree avl;
    avl.Insert(
14 );
    avl.Insert(
11 );
    avl.Insert(
13 );
    avl.Insert(
1 );
    avl.Insert(
4 );
    avl.Insert(
3 );
    avl.Insert(
15 );
    avl.Insert(
2 );
    avl.Insert(
9 );
    avl.Insert(
10 );
    avl.Insert(
8 );
    avl.Insert(
7 );

    avl.Delete(
10 );
    avl.Delete(
8 );
    avl.Delete(
7 );
    avl.Delete(
13 );
#ifdef _DEBUG
    avl.PrintTree();
#endif

    
return   0 ;
}

代码中有些注释显示得不太正常,这是因为这个博客中的代码部分不适用等宽字符的缘故,拿到你的IDE下看就正常了。

转自:http://www.cppblog.com/guogangj/archive/2009/10/26/99502.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值