zoukankan      html  css  js  c++  java
  • 递归改非递归

    递归用的场合很多,比如求一棵树的深度,树查找节点等,递归的好处就是代码简洁,代码易读,缺点是效率不高,深度限制。随着树的深度增加,程序对函数栈空间的使用越来越多,由于栈空间有限( 栈大小受编译器限制,例如VC,VS2003默认1M),递归方法可能导致内存耗尽问题。

    解决方法有两个:

    • 使用非递归算法,例如实现前序、中序、后序遍历,即仿照递归算法执行时的函数工作栈的变化状况,建立一个栈对当前路径上的节点进行记录( 可以用Queue,Stack,HashTable或其它都可以 ),然后根据栈顶元素是否存在左右节点的不同情况决定下一步操作;
    • 使用线索二叉树,即根据遍历规则,在每个叶子上增加指向后续节点的指针。

    递归算法改成非递归算法也很多方法,这里给出两个例子:

    1. 循环设定所有控件和子控件的Text属性:

    递归:

    private void SetTextAll()
    {
        /* 调用 */
        foreach (System.Web.UI.Control ctl in this.Controls)
        {
            SetControlText(ctl); /* 递归 */
        }
     
        SetControlText_New(this.Controls);/* 非递归 */
    }
     
    /// <summary>
    /// 递归方法设置UI控件的Text
    /// </summary>
    public void SetControlText(System.Web.UI.Control control)
    {
        if (control == null) return;
     
        control.Text = "abc";
     
        if (control.Controls.Count > 0)
        {
            foreach (System.Web.UI.Control ctl in control.Controls)
            {
                SetControlText(ctl);
            }
        }
    }

    非递归:

    /// <summary>
    /// 非递归方法设置UI控件的Text
    /// </summary>
    public void SetControlText_New(System.Web.UI.Control.ControlCollection c)
    {
        if (c == null) return;
     
        System.Collections.Queue<Control> q = new System.Collections.Queue<Control>();
                    
     
        foreach (Control control in c)
        {
            Control temp = control;
            bool IsHasChildFolder = true;
            q.Clear();
     
            while (IsHasChildFolder)
            {
                foreach (Control ctl in temp.Controls)
                {
                    ctl.Text = "abc";
     
                    if (ctl.Controls.Count > 0)
                    {
                        q.Enqueue(ctl);
                    }
                }
     
                if (q.Count > 0)
                {
                    temp = q.Dequeue();
                }
                else
                {
                    IsHasChildFolder = false;
                }
            }
        }
    }

    2. 在TreeView中查找某个节点:

    递归:

    private TreeNode FindNode( TreeNode tnParent, string strValue )
     
    {
     
        if( tnParent == null ) return null;
     
        if( tnParent.Text == strValue ) return tnParent;
     
     
     
        TreeNode tnRet = null;
     
        foreach( TreeNode tn in tnParent.Nodes )
     
        {
     
            tnRet = FindNodeExt( tn, strValue );
     
            if( tnRet != null ) break;
     
        }
     
        return tnRet;
     
    }

    非递归:

    private TreeNode FindNode( TreeNode  tnParent, string strValue )
     
    {
     
        if( tnParent == null ) return null;
     
     
     
        if( tnParent.Text == strValue ) return tnParent;
     
        else if( tnParent.Nodes.Count == 0 ) return null;
     
     
     
        TreeNode tnCurrent, tnCurrentPar;
     
     
     
        //Init node
     
        tnCurrentPar = tnParent;
     
        tnCurrent = tnCurrentPar.FirstNode;
     
     
     
        while( tnCurrent != null && tnCurrent != tnParent )
     
        {
     
            while( tnCurrent != null )
     
            {
     
                if( tnCurrent.Text == strValue ) return tnCurrent;
     
                else if( tnCurrent.Nodes.Count > 0 )
     
                {
     
                    //Go into the deepest node in current sub-path
     
                    tnCurrentPar = tnCurrent;
     
                    tnCurrent = tnCurrent.FirstNode;
     
                }
     
                else if( tnCurrent != tnCurrentPar.LastNode )
     
                {
     
                    //Goto next sible node
     
                    tnCurrent = tnCurrent.NextNode;
     
                }
     
                else
     
                    break;
     
            }
     
               
     
            //Go back to parent node till its has next sible node
     
            while( tnCurrent != tnParent && tnCurrent == tnCurrentPar.LastNode )
     
            {
     
                tnCurrent = tnCurrentPar;
     
                tnCurrentPar = tnCurrentPar.Parent;
     
            }
     
     
     
            //Goto next sible node
     
            if( tnCurrent != tnParent )
     
                tnCurrent = tnCurrent.NextNode;
     
        }
     
        return null;
     
    }

    调用:

    /*程序调用*/
     
    TreeNode tnRet = null;
     
    foreach( TreeNode tn in yourTreeView.Nodes )
    {
     
        tnRet =  FindNodeExt( tn, yourValue );
     
        if( tnRet != null ) break;
     
    }
  • 相关阅读:
    直线方程和直线系方程
    多个参数之和积的取值范围
    解析几何习题
    React之Perf
    一文看懂npm、yarn、pnpm之间的区别
    Cannot read property 'properties' of undefined
    为什么要用PolyFill(JS中的修补匠)
    es6-promise
    原生js实现each方法
    有趣的js获取input标签中光标的索引
  • 原文地址:https://www.cnblogs.com/Mainz/p/1162718.html
Copyright © 2011-2022 走看看