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
三分钟……

    原文作者:AVL树
    原文地址: https://blog.csdn.net/zzyu5ds/article/details/45342469
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞