4底2分化查找程序的作业树

                

                    

 

 

                                      《树型软件工程方法》之系列博文4

       底2分化查找程序的作业树

 

               

 


  

 

                        TREESOFT

 

 

 


                             目  录

4 底2分化查找程序的作业树. 1

4.1 问题需求.... 1

4.2 算法设计.... 1

4.2.1 整数的底2分化.... 1

4.2.2 查找算法.... 2

4.3 作业树.... 3

4.3 遍历编程.... 5

4.4 结束语.... 6

 

中国人为什么不可以有自己的软件工程方法及其开发工具平台!

这是介绍《树型软件工程方法》的系列博文,请按文章标题所带的编号顺序阅读,否则你会看不懂本文。

 


4 底2分化查找程序的作业树     

    在有序序列中查找一个已知元素的方法有多种,此前介绍过“常用二分查找”,还有“斐波拉契查找”。本文将介绍另一种查找方法,称为“底2分化查找”。底2分化查找不但具有最优的查找性能,而且算优美而富于艺术。本文将详细介绍该算法,并以作业树来表示之,以进一步实践作业树的设计方法。作业树的相关概念,仍请参看博文“冒泡排序程序的结构化设计”。

4.1 问题需求

    已知有序元素序列V=[v(1), v(2), …, v(n)],该序列中的元素以升序排列,即总有:

        v(j)<v(j+1)

现在有已知元素u,要求在V中找出u,或告知u不在V中。

4.2 算法设计

4.2.1 整数的底2分化

    我们知道,对于任意一个正整数N,总可以用二进制表示如下:

       

         

    这里m=1+(2(N))的整数部xi的确定是同N有关的。辟如N=10=23+21=(1010)2m=1+(2(10))的整数部=1+3=4现在,我们来将N表示成所谓“底2分划”的形式。

    在N的二进制表示中,凡xi0的位都向高位借取一半的数,这样形成的和式就是N的底2分划形式。

      

        z=i-(xi-1)的非yi=2z

    上式就是N的底2分划形式,这里恒有yi+1yi1。式“z=i-(xi-1)的非”体现了“凡xi0的位都向高位借取一半的数”这句话:如果xi-1=0,说明N的二进制表达式中的第i-1项为0,需向第i项借取一半的数,0取非等于1z=i-(xi-1)的非=i-1就实现了借位;如果xi-1=1,说明N的二进制表达式中的第i-1项为1,无需向第i项借位,1取非等于0z=i-(xi-1)的非=i-0=i就实现了不借位。例如N=10=23+21=22+22+20+20就是正整数10的底2分化式。

    与N的二进制表示相比,N的底2分化中各项都不为0。式中的yi都是2的整数次幂,视其为yi个节点,则可生成一棵如图4.1所示(23个节点)的二叉树。因为该二叉树根节点的左边总是一棵完全二叉树,根节点的右边为空,故称之为左满右空二叉树,简称左满树。将所有属于Nm棵左满树的根节点连接后,就得到含N个节点的二叉树,称之为N的底2分化树,简称底2树。如图4.2就是一棵含10个节点的底2树。可以证明,底2树是一类平衡二叉树。

                                             

               4.1 23个节点的左满树                           4.2 22+22+20+20个节点的底2

    将N的底2树的节点按其投影顺序编号,或说按自下而上,先左后根再右,子树递归地遍历底2树。则含有10个节点的底2树的节点编号为:12345678910,如图4.2所示。令每个节点对应于有序序列V中相同序号的元素,则对已知元素u的查找就可以在底2树中进行。我们知道,N个节点的二叉树至少有m层,最多有N层(一条线性链)。平衡二叉树是只有m层的二叉树,具有最短的平均路径。底2树是平衡二叉树,以底2树为查找模型就具有最短的平均查找路径,意味着查找的时间复杂度最优。

4.2.2 查找算法

    底2分化查找实际类似于二分查找,也是以近似拆半的步长向左或向右前进,只不过底2分化查找的步长总是2的整数次幂。由于底2树中的节点都对应着V中相同序号的元素,所以v(j)既是V的元素,也是树的节点。一开始,查找总是沿底2树的根节点链(如图4.2中的蓝色节点链)自上而下进行。一旦有u<v(j),查找就会进入以v(j)为根的左满树,直至得出结果:成功找到或告知u不在V中。现在我们来设计底2分化查找算法,首先要确定查找过程中前进或后退的步长。

    先确定查找沿左满树根节点链(简称根链)前进的步长,这类步长总等于相应左满树的节点数,也就是底2分化表达式中的ym-i项。我们不打算预先生成N的底2分化式,而是在前一步查找步长的基础上生成本步的查找步长。

    令d为查找步长,其总等于2的整数次幂,且以二进制表示。显然,d的初值为d=(2m-1)2=(xm-100000)2=(1000)2。令c为一位的二进制变量,每当N的二进制串X左移一位时,被移出的数(01)就进入c。令di表示第i次的查找步长,则根链上的di=ym-i;令ci表示第i次左移Xc的值,则ci=xm-i。根据N的底2分化的定义,在di的基础上决定di+1=ym-i-1需要分两步进行:

(1) 求取ym-i-1的最大值

    由底2分化的定义可知,ym-i的值有两种可能:ym-i=2m-iym-i=2m-i-1,称前者为最大值,后者为借后值。由于di=ym-ici+1=xm-i-1

      1.1) 如果ci+1=1,说明ym-i-1并未向ym-i借位,diym-i的最大值,应有di=ym-i=2m-i。此时,将di右移一位就得到了ym-i-1的最大值,相当于做“将di右移ci+1位”即得到了ym-i-1的最大值。

      1.2) 如果ci+1=0,说明ym-i-1已从ym-i借位,diym-i的借后值,应有di=ym-i=2m-i-1。此时的di就等于ym-i=1的最大值,做“将di右移ci+1位”并不改变di的值。

(2) 确定ym-i-1的真实值,以求得di+1= ym-i-1

    执行完步骤1后的dym-i=1的最大值,它还不一定就是真实的ym-i-1,还要看xm-i-2的值。先做“左移X一位入c”,这个c相当ci+2=xm-i-2

       2.1) 如果ci+2=1,说明ym-i=2不必向ym-i=1借位,当前的d就是真实的ym-i=1,亦即第i+1步的查找步长。执行“将d右移c非位”后并未改变d的值。

       2.2) 如果ci+2=0,说明ym-i=2要向ym-i=1借位,执行“将d右移c非位”后,就得到了真实的ym-i=1,亦即第i+1步的查找步长。

    我们看到,上述算法中的cd不同步,当判断di的时候,用到的是ci+1ci+2。为此,我们事先将X串循环左移一位,然后再做“左移X一位入c”就可以解决这个问题。显然c的初值c1=xm-2,正好用来判断ym-1是否被借位。顺便指出,上述算法中cd的下标是为了叙述的方便,程序中并不需要。

    上面的算法是为了求得查找沿根链前进的步长,一旦有u<v(j),查找就会进入以v(j)为根的左满树。而在左满树中查找步长的求解算式是固定的,第i+1步的步长总等于第i步步长的一半,即只要做“将d右移一位”即可。

    设f为标志变量,f=0说明查找沿根链前进,f=1说明查找已进入某左满树。j指向V的元素v(j)变量w=y”标志查找成功,w=n”标志查找失败。

[2分化查找算法]

(1) 输入Num=1+(2(N))的整数部X=(N)2=(xm-1xm-2x1x0)2d=(2m-1)2=(xm-100000)2=(100000)2f=0w=n。X=(将X循环左移一位),左移X一位入c。d=(d右移c非位)j=d

(2) 如果d<1w=y”则打印dw后结束,否则转3

(3) 如果f=0则转4否则转5

(4) <查找沿根链前进>

4.1) 如果u=v(j)则置w=y”,转2

4.2) 如果u<v(j)则置f=1d=(d右移一位)j=j-d,转2

4.3) 如果u>v(j)d=(d右移c)左移X一位入cd=(d右移c非位)j=j+d。转2

(5) <查找在左满树中进行>

5.1) 如果u=v(j)则置w=y”,转2

5.2) 如果u<v(j)d=(d右移一位)j=j-d,转2

5.3) 如果u>v(j)d=(d右移一位)j=j+d,转2

 

4.3 作业树

    有了上述算法,现在就可以设计出相应的作业树了,如图4.3所示。我们看到,这棵作业树比较复杂,程序量也比较大。子细观察就可以看出,这棵作业树是可以进一步优化的。当u=v(j)时,无论f等于01,都是置查找成功标志w=y”;当u<v(j)时,无论f等于01,都要做d=(d右移一位)j=j-d,而重复做f=1也不影响算法逻辑;只有当u=v(j)时,f等于01所做的操作有所不同。优化后的作业树如图4.4所示。

                           图4.3 2分化查找的作业树

                图4.4 优化后的底2分化查找的作业树

 4.4 遍历编程

    遍历图4.4的作业树,就可编出底2分化查找的程序,图4.5就是相应的伪代码程序。在此,我们再一次重述作业树的遍历编程规则:

    从根节点开始,自上而下、先左子树、后右子树、再中子树,子树递归地遍历作业树,每进入一个节点就对其编程。

    下面自左向右的节点排列就是对图4.4作业树节点的遍历顺序。

         C0 C1 C2 L1 C3 L2 C4 L3 L4 L5

    在遍历至每一个节点的同时,“每进入一个节点就对其编程”。所谓对节点编程,就是将每个节点中各部分的内容写出来。对于每一个作业节点,其各部分的编程顺序为:

    注释部  顺序部  逻辑表达式部和控制类型部

[2分化查找的伪代码程序]

//C02分化查找//

    Bsearch(N,u)

    {//C1//

f=0w=“n”

X=(N)2=(xm-1xm-2…x1x0)2;

d=(2m-1)2

X=(X循环左移一位);

左移X一位入c

d=(d右移c非位)j=d

while (d1w=n)

   {//C2//

     if (u=v(j))

           {// L1:成功找到//

              w=y;

           }

      else

          {//C3//

             if (u<v(j))

                {//L2:在左满树中向后查找//

                   f=1

                         d=(d右移一位)

                         j=j-d;

                }

             else

               {//C4:生成不同的向前步长//

                  If (f=0)

                      {// L3:沿根链向前查找//

                          d=(d右移c);

             左移X一位入c;

                          d=(d右移c非位);

                           j=j+d;

                       }

           else

           {//L4:在左满树中向前查找//

                       d=(d右移一位);

                        j=j+d;

                     }

               }//节点C4的程序结尾//

        }//节点C3的程序结尾//

    }//节点C2的程序结尾//

 }//节点C1的程序结尾//

return (w,j);

}//节点C0的程序结尾//

 图4.5 底2分化查找的伪代码程序

4.5 结束语

    本文介绍的底2分化查找算法的确具有最优的查找性能,且以移位替代了除法,但程序量相对大了一点。当然,图4.4的作业树还可以进一步优化。辟如,可以将L3L4中的“j=j+d”操作放在C4的中儿子中,以免重复写这条语句。还有,再做稍大点的调整后,操作“d=(d右移一位)j=j-d”亦可以放入控制节点的中儿子中,减少重复编写这两条语句。感兴趣的读者可以试着做上述两项修改。一眼就能看出优化处也是用作业树表示算法的一大好处,在用叙述或程序表示的算法中找出并优化程序就不太直观。

    世界上有数不清的函数级求解的问题,但写文章找例子却不容易。一是要多数能都相对熟悉,二是要能说明论题。早年有“子程序汇编”之类的书,有时间的话也可编写一本“作业树汇编”,这当然需要众人拾柴火焰高,不是那一个人或几个人能完成的。

 

转载于:https://my.oschina.net/treesoft/blog/73261

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值