• c# 用非递归的写法实现递归


    最近写代码碰到了一个bug,就是递归次数太多爆堆栈了,然后就写了一个递归工具来解决这个问题。

    1. using System;
    2. using System.Collections.Generic;
    3. ///
    4. /// 递归工具
    5. ///
    6. public static class RecursionTool
    7. {
    8. //递归方式 1 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    9. ///
    10. /// 树节点接口
    11. ///
    12. public interface ITreeNode
    13. {
    14. ///
    15. /// 访问标记
    16. ///
    17. bool Visited { get; set; }
    18. ///
    19. /// 子节点
    20. ///
    21. List Children { get; set; }
    22. }
    23. ///
    24. /// 递归算法的非递归实现
    25. /// 以节点树的方式递归
    26. ///
    27. public static (bool result, object args) Recursive(
    28. IEnumerable rootNodes,
    29. Funcbool result, object args)> handleNode)
    30. {
    31. var stack = new Stack();
    32. foreach (var item in rootNodes)
    33. {
    34. item.Visited = false;
    35. stack.Push(item);
    36. }
    37. while (stack.Count > 0)
    38. {
    39. var rootNode = stack.Peek();
    40. //没访问过,且有子节点时
    41. if (rootNode.Visited == false && rootNode.Children != null && rootNode.Children.Count > 0)
    42. {
    43. rootNode.Visited = true;
    44. //把子节点全部入栈
    45. foreach (var item in rootNode.Children)
    46. {
    47. item.Visited = false;
    48. stack.Push(item);
    49. }
    50. }
    51. //访问处理根节点
    52. else
    53. {
    54. rootNode = stack.Pop();
    55. rootNode.Visited = false;
    56. if (handleNode != null)
    57. {
    58. var tuple = handleNode(rootNode);
    59. if (tuple.result)
    60. {
    61. return tuple;
    62. }
    63. }
    64. }
    65. }
    66. return (false, null);
    67. }
    68. //递归方式 2 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    69. ///
    70. /// 递归状态
    71. ///
    72. public enum ERecursiveState
    73. {
    74. Finish,
    75. Next,
    76. Skip,
    77. }
    78. ///
    79. /// 递归算法的非递归实现
    80. /// 根据回调里的逻辑递归
    81. ///
    82. public static (bool result, object args) Recursive<TNode>(
    83. IEnumerable rootNodes,
    84. Funcbool result, object args, IEnumerable nexts)> handleNode)
    85. {
    86. var stack = new Stack();
    87. foreach (var item in rootNodes)
    88. {
    89. stack.Push(item);
    90. }
    91. while (stack.Count > 0)
    92. {
    93. var rootNode = stack.Pop();
    94. if (handleNode != null)
    95. {
    96. var tuple = handleNode(rootNode);
    97. switch (tuple.state)
    98. {
    99. case ERecursiveState.Finish:
    100. return (tuple.result, tuple.args);
    101. case ERecursiveState.Next:
    102. {
    103. if (tuple.nexts != null)
    104. {
    105. foreach (var item in tuple.nexts)
    106. {
    107. stack.Push(item);
    108. }
    109. }
    110. }
    111. break;
    112. }
    113. }
    114. }
    115. return (false, null);
    116. }
    117. }

    也很久没写文章了,顺手记录一下。

  • 相关阅读:
    RabbitMQ集群运维实践
    【C++项目】手动实现一个定长内存池(了解内存分配机制、定长内存提高效率 附源码)
    java基于微信小程序的社区心理健康咨询辅导服务系统 uniapp 小程序
    【大数据Hive】hive 多字段分隔符使用详解
    【k8s部署elasticsearch】k8s环境下安装elasticsearch集群和kibana
    新版Android Studio中设置gradle的JDK版本
    栈的应用场景(二)
    linux安装zookeeper
    面试:gradle添加自定义task
    LeetCode C++ 67.二进制求和
  • 原文地址:https://blog.csdn.net/WPAPA/article/details/133797537