递归改非递归
递归用的场合很多,比如求一棵树的深度,树查找节点等,递归的好处就是代码简洁,代码易读,缺点是效率不高,深度限制。随着树的深度增加,程序对函数栈空间的使用越来越多,由于栈空间有限( 栈大小受编译器限制,例如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;
}