递归改非递归
递归用的场合很多,比如求一棵树的深度,树查找节点等,递归的好处就是代码简洁,代码易读,缺点是效率不高,深度限制。随着树的深度增加,程序对函数栈空间的使用越来越多,由于栈空间有限( 栈大小受编译器限制,例如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;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· [AI/GPT/综述] AI Agent的设计模式综述