zoukankan      html  css  js  c++  java
  • 浅谈splay的双旋

    昨晚终于明白了splay双旋中的一些细节,今日整理如下

    注:题目用的2002HNOI营业额统计,测试结果均来及codevs 网站的评测结果 http://codevs.cn/problem/1296/

    本题完整代码请见http://www.cnblogs.com/TheRoadToTheGold/p/6372009.html

    1、这是旋转部分的代码

    inline void splay(int x,int goal)
            {            
                while(pre[x]!=goal)
                {
                    int y=pre[x];
                    int kind=ch[y][0]==x;
                    if(pre[y]==goal) rot(x,kind);//父节点是目标节点,单旋
                    else
                    {
                        kind=ch[pre[y]][0]==y;
                        if(ch[y][!kind]==x)//一字型
                        {                        
                            rot(y,kind);
                            rot(x,kind);
                        }
                        else//之字型
                        {
                            rot(x,!kind);
                            rot(x,kind);
                        }
                    }
                }
                root=x;
            }

    理解较浅,目前认为之字形旋转的本质就是单旋,一字型才算双旋

    2、双旋与单旋的区别

    先看看运行结果

    左边是单旋,右边是双旋,空间几乎一样,时间差距很大

    why?    

     图1:

    图2的单旋结果

             

     图2:

    双旋结果                                                                                                                        

               

    可以发现,双旋之后的层数要比单旋之后的层数少1

    这只是5层(本图中第6层对5不干扰),如果层数更多呢

    所以,双旋层数比单旋要更少

    手推一下,上图中第1次旋转结果的树的形态与单旋结果的树的形态是一样的,只是4和3换了个位

    所以双旋的优越性在一字型层数>4时才会体现

    为什么双旋层数要少?

    继续观察图2的第2个和第3个,发现少的那一层是因为4和1处在了同一层

    即双旋 使 待旋转点的旋转方向的孩子 与待旋转点的爷爷节点  处在同一层

    换用字母表示:

    设a的旋转方向的孩子是b,a的父节点是c,c的父节点是d

    那么双旋使b、d处在同一层,因为b、d都成为了c的孩子

    为什么?分析双旋的两次旋转

    先旋转父节点,使爷爷节点和自己都成为父节点的孩子,此时父节点和自己处在同一层,原来的爷爷节点成为自己的父节点

    然后旋转自己,自己旋转方向的孩子节点成为自己现在父节点(原先爷爷节点)的孩子,也就是和自己原先父节点处在了同一层

    这也是我认为之字型旋转也是单旋的原因,因为之字型旋转是让自己旋转2次,与单旋并无不同

    3、旋转顺序

    A、代码中一字型旋转顺序是先转父节点,再转自己

    ①不能改成先转自己,再转父节点

    先转自己让自己到父节点的位置,父节点到自己的孩子位置,再转父节点,又转回去了,跟没转一个样

    ②可以改成旋转自己两次,但那样就相当于单旋

    B、之字型旋转的旋转顺序是连续转自己2次

    看图,

    可以发现连续转自己两次,每次使自己上移一层

    而如果先转父节点,可以发现自己原来在哪儿还在那儿,只是父节点和爷爷节点换了而已,相当于这一次白转了

    当然你也可以先转父节点,再转自己(两次旋转方向相同),因为的正确性是有保证的

    对比一下,上边是先转父节点,再转自己,下边是连续转自己两次(一字型旋转均是先转父节点,再转自己)

    上边空间明显大,时间也多点儿

             

  • 相关阅读:
    浏览器跨域访问WebApi
    外部主机无法访问IIS发布的网站
    在VisualStudio中远程调试IIS站点
    关于跨域请求的一些解决方案
    MVC与WebApi中的异常过滤器
    委托与事件
    C#中的属性
    C#中的索引
    Equals与==的区别
    关于跨域响应头Access-Control-Allow-Headers的一些说明
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/6372344.html
Copyright © 2011-2022 走看看