口胡平衡树splay

一.什么是平衡树

就这样给你说,平衡树就是一个节点的左儿子严格小于它,右儿子严格大于它的一棵二叉树,整个树的叶子结点的深度几乎一致。

二.分步讲解

1.定义变量

key[i]:排序的关键字
cnt[i]:每个节点的数的个数
f[i]:父节点
ch[i][0]:左儿子;ch[i][1]:右儿子
siz[i]:以i为根的子树大小
sz:节点总数
root:根节点的编号

4.预备函数

void clear (int x){
   //清零
    ch[x][0] = ch[x][1] = key[x] = cnt[x] = f[x] = siz[x] = 0;
}

void update (int x){
   //更新
    siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + cnt[x];
}

3.旋转操作

给一张图就行了
在这里插入图片描述
看懂了吗?

void rotate (int x){
   
    int fa = f[x], gfa = f[fa], d = (x == ch[fa][1]);//d是找x是fa的哪一个儿子节点
    ch[fa][d] = ch[x][1 ^ d];
    f[ch[fa][d]] = fa;//***
    ch[x][1 ^ d] = fa;
    f[fa] = x;
    f[x] = gfa;
    if (gfa){
   
        int d1 = (fa == ch[gfa][1]);
        ch[gfa][d1] = x;
    }
    update (x), update (fa), update (gfa);//注意更新
}

3.splay

splay的作用就是把当前节点旋转到根,那么根就更新了,并且树是平衡的。

void splay (int x){
   
    for (int fa; fa = f[x]; rotate(x))
        if (f[fa])
            rotate ((ch[f[fa]][1] == fa) == (ch[fa][1] == x) ? fa : x);
            //这里要注意,如果当前节点,父亲节点和爷爷节点在一条线上,就要先旋转父亲节点,再旋转当前节点,注意不能失衡
    root = x;
}

4.插入

void insert (int x){
   
    if (! root){
   //第一种情况,是空树
        sz ++;
        ch[sz][0] = ch[sz][1] = f[sz] = 0;
        cnt[sz] = siz[sz] = 1;
        key[sz] = x;
        root = sz;
        return ;
    }
    int now = root, fa = 0;
    while (1){
   //第二种情况,要插到叶节点去
        if (key[now] == x){
   
            cnt[now] ++;
            update (now);
            update (fa);
            splay (now);//注意要旋转到根部
            return ;
        }
        fa = now
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值