二叉树左旋右旋

额,今天先更左旋右旋,当然加强版的线段树正在来的路上。。。

左旋右旋,就是说可以用来平衡二叉树,加强二叉树的效率。

如果阅读上有些困难,建议画一个图来看。

#include<cstdio>

#include<cstdlib>

using namespace std;

int n;

struct node

{

    int d;

    int rnd;

    node *parent;

    node *ch[2];

}pool[100100],*root;

void insert (node *r,node *p)//建树

{

    if(r->d >= p->d)

    {

        if(r->ch[0]==0)

            r->ch[0]=p,p->parent=r;

        else

            insert(r->ch[0],p);

    }

    else

    {

        if(r->ch[1]==0)

            r->ch[1]=p,p->parent=r;

        else

            insert(r->ch[1],p);

    }

}

void rotate_left(node *p) //左旋

{

    node *parent=p->parent,*lson=p->ch[0],*gp=p->parent->parent;

    parent->ch[1]=lson;//父的右子变成左旋点的左子

    if(lson) lson->parent=parent;//如果左旋点左子存在,左旋点左子的父就从左旋点变成左旋点的父

    p->ch[0]=parent;//左旋点的左子变成左旋点的父

    parent->parent=p;//左旋点的父,也就是变完左旋点的左子的父是左旋点

    p->parent=gp;//左旋点的父变成开始左旋点的父的父

    if(parent==root) {root=p; return;}//如果说开始左旋点的父是根的话,现在左旋点是根

    if(gp->ch[0]==parent) gp->ch[0]=p;//如果开始左旋点的父是左旋点的父的父的左子,那么现在开始左旋点的父的父的左子变为左旋点

    else gp->ch[1]=p;//反之

}

void rotate_right(node *p)// 与左旋同样的道理

{

    node *parent=p->parent,*rson=p->ch[1],*gp=p->parent->parent;

    parent->ch[0]=rson;

    if(rson) rson->parent=parent;

    p->ch[1]=parent;

    parent->parent=p;

    p->parent=gp;

    if(parent==root) {root=p; return;}

    if(gp->ch[0]==parent) gp->ch[0]=p;

    else gp->ch[1]=p;

}

void treap(node *p) //判断左旋还是右旋

{

    if(root == p || p->rnd >= p->parent->rnd) return;//如果已经是根,或者子的数已经比父的数要大,不需要平衡

    if(p->parent->ch[0] == p) rotate_right(p);//左子右旋

    else rotate_left(p);//右子左旋

    treap(p);

}

void inorder(node *p)//中序打印

{

    if(p->ch[0]) inorder(p->ch[0]);

    printf("%d ",p->d);

    if(p->ch[1]) inorder(p->ch[1]);

}

void input() //简单输入

{

    scanf("%d",&n);

    for(int i=1;i<=n;i++)

    {

        scanf("%d",&pool[i].d);//输入一个数

        pool[i].rnd=rand();//再随机生成一个数,做左旋右旋

    }

    root=&pool[1];

    for(int i=2;i<=n;i++)

    {

        insert(root,&pool[i]);//每插入一次就平衡一次

        treap(&pool[i]);

    }

    inorder(root);

}

int main()

{

    input();

    return 0;

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值