AVL树的简单写法

为什么现在AVL树都是利用一些高端的node类而不是利用数组来维护二叉树结点属性
像我这语言不精的人就看不懂,并且代码量都偏大。
二叉树中,left和right属性都是比较对称的,为什么不利用它将代码精简?
比如说AVL树的Balance:

bool Balance(int x,bool y){
        if(h[son[x][y]]>h[son[x][!y]]+1){
            if(h[son[son[x][y]][y]]<h[son[son[x][y]][!y]])
                Rotate(son[x][y],y);
            Rotate(x,!y);
            return 1;
        }
        return 0;
    }

只有9行,合并了旋转(Rotate(int x,bool y))
合并了两种不平衡情况,并且为什么要是 bool 型,这在Insert中会有交代。
注:y==0时表明左子树高
y==1时表明右子树高。

合并后的Rotate(int x,bool y):

void Rotate(int x,bool t){
        int y=son[x][!t];
        son[x][!t]=son[y][t];
        if(son[y][t])
            pre[son[y][t]]=x;
        pre[y]=pre[x];
        if(pre[x]==0)
            root=y;
        else{
            son[pre[x]][x==son[pre[x]][1]]=y;
        }
        son[y][t]=x;
        pre[x]=y;
        h[x]=max(h[son[x][0]],h[son[x][1]])+1;
        h[y]=h[x]+1;
    }

//此外我想问一下,为什么代码字体颜色变了
这里将CLRS中的两个Rotate()合为了一个。
注:y==0时是左旋,右子树较高。
y==1时是右旋,左子树较高。

Insert函数:

void Insert(int t,int value){
        int y=root,x=0;
        T[t]=value;
        if(y==0)
            root=t;
        else{
            while(y){
                x=y;
                y=son[y][T[y]<value];
            }
            son[x][T[x]<value]=t;
        }
        pre[t]=x;
        h[t]=1;
        son[t][0]=0,son[t][1]=0;
        while(x){
            y=h[x];
            h[x]=max(h[son[x][0]],h[son[x][1]])+1;
            if(h[x]==y||Balance(x,T[x]<value))
                break;
            x=pre[x];
        }
    }

仍然抄的CLRS中的Insert。
但你可能会怀疑

if(h[x]==y||Balance(x,T[x]<value))
                break;

为什么要break;
因为当 当前要平衡的树高度不变时,那么其父结点及以上的结点都还是平衡的;
而若该结点进行了Balance,那么它的高度一定不变(但它没怎么节省时间,我只是为了节约行数);
你可以改成:

if(h[x]==y)
    break;
Balance(x,T[x]<value);

这下有三行了。

而令人心疼的是Delete()
既不能简化又不能中途break;
Delete:

void Transplant(int x,int y){
    if(pre[x]==0)
        root=y;
    else{
        son[pre[x]][x==son[pre[x]][1]]=y;
    }
    if(y)
        pre[y]=pre[x];
}
int maximum(int x){
    while(son[x][1])
        x=son[x][1];
    return x;
}
void Delete(int x){
    int y=son[x][0],z=pre[x],v=0;
    if(y==0){
        v=son[x][1];
        Transplant(x,son[x][1]);
    }
    else{
        if(son[x][1]==0){
            v=son[x][0];
            Transplant(x,son[x][0]);
        }
        else{
            y=maximum(y);
            z=pre[y];
            if(z!=x){
                v=son[y][0];
                Transplant(y,son[y][0]);
                son[y][0]=son[x][0];
                pre[son[y][0]]=y;
            }
            else{
                v=y;
            }
            Transplant(x,y);
            son[y][1]=son[x][1];
            pre[son[y][1]]=y;
        }
    }
    while(z){
        h[z]=max(h[son[z][0]],h[son[z][1]])+1;
        Balance(z,son[z][0]==v);
        v=z;
        z=pre[z];
    }
}

CLRS上的Delete简化不了;
但Search稍稍简化了;
Search:

int search(int value){
        int x=root;
        while(x){
            if(T[x]==value)
                return x;
            x=son[x][T[x]<value];
        }
        return 0;
    }

代码共计106行。此外,T.nil=0,即哨兵为0;
给出10000000=10^7个随机数据插入到AVL树中用时:
15804ms
16002ms
15804ms
16秒
h=27
都是一组数据;
而直接插入二叉树中用时:AVL树的简单,数组写法
188473ms
186718ms
186191ms
三分钟……

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值