zoukankan      html  css  js  c++  java
  • 将树形递归转换为loop

    class Stack(object):
        def __init__(self,**kwargs):
            self.__dict__.update(kwargs)
        def __str__(self):
            return '|'.join(
                ['%s:%s'%(k,getattr(self,k))
                 for k in sorted(self.__dict__)])
        __repr__ = __str__
    
    def fab(n):
        if n==1 or n==2:
            return 1
        return fab(n-1) + fab(n-2)
    
    def xfab(n):       
        rst = 0
        stack = [Stack(n=n,stage=0)]
        while stack:
            #print(stack,rst)
            crt=stack.pop()
            if crt.stage == 0: 
                if crt.n == 1 or crt.n == 2:
                    rst = 1
                    continue
                else:
                    crt.stage = 1
                    stack.append(crt)
                    stack.append(Stack(n=crt.n-1,stage=0)) 
                    continue               
            if crt.stage == 1: 
                crt.adv = rst
                crt.stage = 2
                stack.append(crt)
                stack.append(Stack(n=crt.n-2,stage=0))            
                continue
            if crt.stage == 2:
                rst = crt.adv + rst
                continue        
        return rst

    虽然loop繁杂多了,但是它有以下好处:

    1.不会像递归函数那样栈溢出

    2.对递归过程有了更多控制,例如你可以选择广度优先

    再如:

    #----------递归--------------------------------
    def tmove(n,a=0,b=1,c=2):
        if n==1:
            yield a,c
        else:
            yield from tmove(n-1,a,c,b)
            yield a,c
            yield from tmove(n-1,b,a,c)
    
    def fmove(n,a=0,b=1,c=2,d=3):
        if n==1:
            yield a,d
        else:
            i = int((math.sqrt(1+8*n)-1)/2)
            yield from fmove(n-i,a,d,b,c)
            yield from tmove(i,a,b,d)
            yield from fmove(n-i,c,b,a,d)          
    
    #----------循环--------------------------------
    def xtmove(n,a=0,b=1,c=2):
        stack = [Stack(n=n,a=a,b=b,c=c,stage=0)]
        while stack:
            crt=stack.pop()    
            if crt.n == 1:
                yield crt.a,crt.c
                continue
            if crt.stage==0:
                crt.stage=1
                stack.append(crt)
                stack.append(Stack(n=crt.n-1,a=crt.a,b=crt.c,c=crt.b,stage=0))
                continue
            if crt.stage==1:
                yield crt.a,crt.c
                stack.append(Stack(n=crt.n-1,a=crt.b,b=crt.a,c=crt.c,stage=0))
    
    def xfmove(n,a=0,b=1,c=2,d=3):
        stack = [Stack(n=n,a=a,b=b,c=c,d=d,stage=0)]
        while stack:
            crt=stack.pop()
            if crt.n == 1:
                yield crt.a,crt.d
                continue
            i = int((math.sqrt(1+8*crt.n)-1)/2)
            if crt.stage==0:
                crt.stage=1
                stack.append(crt)
                stack.append(Stack(n=crt.n-i,a=crt.a,b=crt.d,c=crt.b,d=crt.c,stage=0))
                continue
            if crt.stage==1:
                yield from xtmove(n=i,a=crt.a,b=crt.b,c=crt.d)
                stack.append(Stack(n=crt.n-i,a=crt.c,b=crt.b,c=crt.a,d=crt.d,stage=0))
    
    if __name__=='__main__':
        for x,y in xfmove(10000000000):
            pass
        for x,y in fmove(10000000000):
            pass

    虽然不太清楚实践中会不会出现这种巨大的参数以至于让递归栈溢出,但至少心里有个底了,以后处理复杂问题,先构建递归函数,再写个loop版.

    小参数用递归,大参数就用loop.

  • 相关阅读:
    MQTT协议探究(三)
    MQTT协议探究(二)
    MQTT协议探究(一)
    MQTT图形化客户端比较
    Ubuntu编写开机启动脚本
    线程阻塞释放的5种方法
    (转)Linux vmstat命令实战详解
    (转)MongoDB 3.0 WT引擎参考配置文件
    (转)mongodb常用命令脚本化-自动化运维
    (转)MongoDB 实现currentOp定时捕获
  • 原文地址:https://www.cnblogs.com/xiangnan/p/3569772.html
Copyright © 2011-2022 走看看