最近写代码碰到了一个bug,就是递归次数太多爆堆栈了,然后就写了一个递归工具来解决这个问题。
using System;
using System.Collections.Generic;
/// <summary>
/// 递归工具
/// </summary>
public static class RecursionTool
{
//递归方式 1 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
/// <summary>
/// 树节点接口
/// </summary>
public interface ITreeNode
{
/// <summary>
/// 访问标记
/// </summary>
bool Visited { get; set; }
/// <summary>
/// 子节点
/// </summary>
List<ITreeNode> Children { get; set; }
}
/// <summary>
/// 递归算法的非递归实现
/// 以节点树的方式递归
/// </summary>
public static (bool result, object args) Recursive(
IEnumerable<ITreeNode> rootNodes,
Func<ITreeNode, (bool result, object args)> handleNode)
{
var stack = new Stack<ITreeNode>();
foreach (var item in rootNodes)
{
item.Visited = false;
stack.Push(item);
}
while (stack.Count > 0)
{
var rootNode = stack.Peek();
//没访问过,且有子节点时
if (rootNode.Visited == false && rootNode.Children != null && rootNode.Children.Count > 0)
{
rootNode.Visited = true;
//把子节点全部入栈
foreach (var item in rootNode.Children)
{
item.Visited = false;
stack.Push(item);
}
}
//访问处理根节点
else
{
rootNode = stack.Pop();
rootNode.Visited = false;
if (handleNode != null)
{
var tuple = handleNode(rootNode);
if (tuple.result)
{
return tuple;
}
}
}
}
return (false, null);
}
//递归方式 2 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
/// <summary>
/// 递归状态
/// </summary>
public enum ERecursiveState
{
Finish,
Next,
Skip,
}
/// <summary>
/// 递归算法的非递归实现
/// 根据回调里的逻辑递归
/// </summary>
public static (bool result, object args) Recursive<TNode>(
IEnumerable<TNode> rootNodes,
Func<TNode, (ERecursiveState state, bool result, object args, IEnumerable<TNode> nexts)> handleNode)
{
var stack = new Stack<TNode>();
foreach (var item in rootNodes)
{
stack.Push(item);
}
while (stack.Count > 0)
{
var rootNode = stack.Pop();
if (handleNode != null)
{
var tuple = handleNode(rootNode);
switch (tuple.state)
{
case ERecursiveState.Finish:
return (tuple.result, tuple.args);
case ERecursiveState.Next:
{
if (tuple.nexts != null)
{
foreach (var item in tuple.nexts)
{
stack.Push(item);
}
}
}
break;
}
}
}
return (false, null);
}
}
也很久没写文章了,顺手记录一下。