AVL搜索树

AVL搜索树是二叉排序数的一个改进,在AVL中任何两个儿子子树的高度差不超过1,故查找、删除、插入在平均和最坏情况下都是O(logn)。

代码如下:

#include<iostream>
#include<cstdlib>
#include<ctime>
#include<cstdio>
#include<cmath>
using namespace std;
typedef struct AVLTree{
  int nData,nHeight;
  struct AVLTree* pLeft;
  struct AVLTree* pRight;
}AVLTree;
int max(int a,int b);
int Height(AVLTree* pNode);
AVLTree* Insert(int nData,AVLTree *pNode);
AVLTree* LLRotate(AVLTree* pNode);
AVLTree* RRRotate(AVLTree* pNode);
AVLTree* LRRotate(AVLTree* pNode);
AVLTree* RLRotate(AVLTree* pNode);
void DeleteTree(AVLTree** ppRoot);
void PrintTree(AVLTree* pRoot);

int main()
{
    int i,x;
    AVLTree* pRoot = NULL;
    srand((unsigned int)time(NULL));
    for (i = 0; i < 20; i++){
        x = rand() % 100;
        cout<<x<<' ';
        pRoot = Insert(x,pRoot);
    }
    cout<<endl;
    PrintTree(pRoot);
    DeleteTree(&pRoot);
    return 0;
}

int max(int a,int b)
{
    return (a>b?a:b);
}

int Height(AVLTree* pNode)
{
    if (pNode == NULL) return -1;
    return pNode -> nHeight;
}

AVLTree* Insert(int nData,AVLTree *pNode)
{
    if (pNode == NULL){
        pNode = (AVLTree* )malloc(sizeof(AVLTree));
        pNode->nData = nData;
        pNode->nHeight = 0;
        pNode->pLeft = pNode->pRight = NULL;
    } else if ( nData < pNode->nData )//插入到左子树中去
    {
        pNode -> pLeft = Insert(nData, pNode -> pLeft);
        if ( Height(pNode -> pLeft) - Height(pNode -> pRight) == 2)
        {
            if (nData < pNode -> pLeft -> nData){
                pNode = LLRotate(pNode);//LL型旋转
            } else pNode = LRRotate(pNode);//LR型旋转
        }
    } else if ( nData > pNode -> nData)//插入到右子树中去
    {
        pNode -> pRight = Insert(nData, pNode -> pRight);
        if ( Height(pNode -> pRight) - Height(pNode -> pLeft) == 2)
        {
            if (nData < pNode -> pRight -> nData){
                pNode = RLRotate(pNode);//RL型旋转
            } else pNode = RRRotate(pNode);//RR型旋转
        }
    }
    pNode -> nHeight = max(Height(pNode -> pLeft),Height(pNode -> pRight)) + 1;
    return pNode;
}

AVLTree* LLRotate(AVLTree* pNode)
{
    AVLTree* p1;
    p1 = pNode -> pLeft;
    pNode -> pLeft = p1 -> pRight;
    p1 -> pRight = pNode;
    pNode -> nHeight = max(Height(pNode -> pLeft),Height(pNode -> pRight)) + 1;
    p1 -> nHeight = max(Height(p1 -> pLeft),pNode -> nHeight) + 1;
    return p1;
}

AVLTree* RRRotate(AVLTree* pNode)
{
    AVLTree* p1;
    p1 = pNode -> pRight;
    pNode -> pRight = p1 -> pLeft;
    p1 -> pLeft = pNode;
    pNode -> nHeight = max(Height(pNode -> pLeft),Height(pNode -> pRight)) + 1;
    p1 -> nHeight = max(Height(p1 -> pRight),pNode -> nHeight) + 1;
    return p1;
}

AVLTree* LRRotate(AVLTree* pNode)
{
    pNode -> pLeft = RRRotate(pNode -> pLeft);
    return LLRotate(pNode);
}

AVLTree* RLRotate(AVLTree* pNode)
{
    pNode -> pRight = LLRotate(pNode -> pRight);
    return RRRotate(pNode);
}

void DeleteTree(AVLTree** ppRoot)
{
    if ( ppRoot == NULL || *ppRoot == NULL)
        return ;
    DeleteTree(&((*ppRoot) -> pLeft));
    DeleteTree(&((*ppRoot) -> pRight));
    free( *ppRoot);
    *ppRoot = NULL;
}

void PrintTree(AVLTree* pRoot)
{
    if (pRoot == NULL ) return;
    static int n = 0;
    PrintTree(pRoot -> pLeft);
    printf("[%d]nData = %d %d\n",++n,pRoot -> nData, pRoot -> nHeight);
    PrintTree(pRoot -> pRight);
}
这里只写了插入操作,查询操作比较简单,删除和插入也很相似,不过要考虑删除当前节点后,用该节点的哪个儿子来代替自己的位置。

插入操作时会出现当前搜索树不再是AVL搜索树的情况,这时需要对树进行维护,有4种情况LL型、LR型、RR型、RL型,学AVL搜索树主要要把这四种情况的维护了解,基本就学会了。

在整个代码过程中,要记得更新节点的高度,方便后续操作。

具体可以看下维基百科:https://zh.wikipedia.org/wiki/AVL%E6%A0%91

例题:poj2418  Hardwood Species 

可以用AVL树练习一下,也可以用其它方法做,代码会在其它blog上贴出

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值