递归时候每次调用自身在堆栈上要记录返回地址,而堆栈的空间很少,调用次数多了后会产生堆栈溢出,以下代码是实际项目中,通过Queue<T>来避免递归算法的代码:

/// <summary>
/// 获取某个节点下特定属性的所有子孙节点
/// </summary>
/// <param name="groupId"></param>
/// <returns></returns>

public IList<OfficeGroupNodeDto> GetSelfAndChildOfficesByGroupId(int groupId)
{
  Func<int, string, BusinessType, int, string, OfficeGroupNodeDto> createGroupNodeFunc =
    (id, name, bizType, parentId, parentName) =>
      new OfficeGroupNodeDto()
      {
        OfficeId = id,
        Name = name,
        BizType = bizType,
        ParentId = parentId,
        ParentName = parentName
      };
  var offices = GetTenantOffices().ToArray();
  Func<int, OfficeDto[]> getChildOfficesFunc = id => offices.Where(x => x.ParentId == id).ToArray();

//创建队列
  var groupNodeCacheQueue = new Queue<OfficeGroupNodeDto>();
  var currentGroup = groupId == 0 || groupId == Office.AdminOffice.Id
    ? ToDto(Office.AdminOffice)
    : offices.FirstOrDefault(x => x.Id == groupId && x.OfficeType == OfficeType.Group);
  if (currentGroup == null) return null;
  var officeGroupNodeDto =
    createGroupNodeFunc(currentGroup.Id, currentGroup.Abbreviation, currentGroup.BizType, 0, string.Empty);

//初始进入队列一个元素
  groupNodeCacheQueue.Enqueue(officeGroupNodeDto);

//循环读取队列内元素,直到读取完
  while (groupNodeCacheQueue.Count > 0)
  {

//出队列一个元素节点

    var currentGroupNode = groupNodeCacheQueue.Dequeue();

    //获取该节点的所有孩子节点
    var childOffices = getChildOfficesFunc(currentGroupNode.OfficeId);
    currentGroupNode.IsGroup = true;
    var hasChildren = childOffices.SafeAny();
    currentGroupNode.HasChildren = hasChildren;
    if (!hasChildren) continue;

//遍历当前节点的孩子节点
    foreach (var office in childOffices)
    {
      if (office.BizType == BusinessType.FranchiseChain) continue;

//创建符合条件的节点
      var newNode = createGroupNodeFunc(office.Id, office.Abbreviation, BusinessType.RegularChain,
        currentGroupNode.OfficeId, currentGroupNode.Name);
      currentGroupNode.Items.Add(newNode);
      if (office.OfficeType == OfficeType.Office) continue;

//把还有子节点的孩子元素节点到队列,待下次循环继续

      groupNodeCacheQueue.Enqueue(newNode);

    }
  }
  return new List<OfficeGroupNodeDto>() { officeGroupNodeDto };
}

注:主要看注释部分的总体思路,其他次要细节不用太关注

  当然这里也可以用其他数据结构如Stack<T>,根据实际需要选择,如有没有顺序要求。

C# 使用Queue<T>代替递归算法遍历树的更多相关文章

  1. POJ 1849 Two(遍历树)

    POJ 1849 Two(遍历树) http://poj.org/problem?id=1849 题意: 有一颗n个结点的带权的无向树, 在s结点放两个机器人, 这两个机器人会把树的每条边都走一遍, ...

  2. Java集合的Stack、Queue、Map的遍历

    Java集合的Stack.Queue.Map的遍历   在集合操作中,常常离不开对集合的遍历,对集合遍历一般来说一个foreach就搞定了,但是,对于Stack.Queue.Map类型的遍历,还是有一 ...

  3. lintcode :前序遍历和中序遍历树构造二叉树

    解题 前序遍历和中序遍历树构造二叉树 根据前序遍历和中序遍历树构造二叉树. 样例 给出中序遍历:[1,2,3]和前序遍历:[2,1,3]. 返回如下的树: 2 / \ 1 3 注意 你可以假设树中不存 ...

  4. lintcode: 中序遍历和后序遍历树构造二叉树

    题目 中序遍历和后序遍历树构造二叉树 根据中序遍历和后序遍历树构造二叉树 样例 给出树的中序遍历: [1,2,3] 和后序遍历: [1,3,2] 返回如下的树: 2 /  \ 1    3 注意 你可 ...

  5. java遍历树(深度遍历和广度遍历

    java遍历树如现有以下一颗树:A     B          B1               B11          B2               B22     C          C ...

  6. LintCode-72.中序遍历和后序遍历树构造二叉树

    中序遍历和后序遍历树构造二叉树 根据中序遍历和后序遍历树构造二叉树 注意事项 你可以假设树中不存在相同数值的节点 样例 给出树的中序遍历: [1,2,3] 和后序遍历: [1,3,2] 返回如下的树: ...

  7. LintCode-73.前序遍历和中序遍历树构造二叉树

    前序遍历和中序遍历树构造二叉树 根据前序遍历和中序遍历树构造二叉树. 注意事项 你可以假设树中不存在相同数值的节点 样例 给出中序遍历:[1,2,3]和前序遍历:[2,1,3]. 返回如下的树:    ...

  8. 问题:Oracle 树形遍历;结果:使用oracle进行遍历树操作

    使用oracle进行遍历树操作   1:首先数据库中表必须是树形结构的 2:super_department_id 为 department_id 的父节点编号 3:以下语句的执行结果是:depart ...

  9. js39---组合模式,查找遍历树

    /** *有这样一个需求 *有一个学校有2个班(一班,二班) *每个班级分2个小组(一班一组,一班二组,二班一组,二班二组) *学校计算机教室有限,每一个小组分着来上课. *考试的时候大家一起考 *请 ...

随机推荐

  1. 在IP网络中,P、PE、CE代表意思

    1.ce , pe属于mpls vpn里的概念.VPN概念中,把整个网络中的路由器分为三类:用户边缘路由器(CE).运营商边缘路由器(PE)和运营商骨干路由器(P):其中,PE充当IP VPN接入路由 ...

  2. JavaScript.how-to-debug-javascript

    How to debug JavaScript code 1. 写一个HTML文件.例如: <!DOCTYPE html> <html> <title>Web Pa ...

  3. 在nginx中,禁止IP访问.只可以使用域名访问.

    if ($host ~* "\d+\.\d+\.\d+\.\d+"){ ; } 其实说白了, 就是进行host主机头过滤,使用正则来判断下.

  4. 64位ubuntu 兼容32位

    http://www.cnblogs.com/mliudong/p/4086797.html 首先要打开64位系统对32位的支持 第一步:确认64为架构的内核 dpkg --print-archite ...

  5. PHP字符串位置相关的函数

    strpos函数 描述:将返回一个字符串在另一个字符串第一次出现的位置 语法:int strpos(string haystack, mixed needle [,int offset]); 相反地 ...

  6. unity延时函数

    新建一个工具类 public class DelayToInvoke : MonoBehaviour{ public static IEnumerator DelayToInvokeDo(Action ...

  7. oracle 分组中排序(rank函数)

    需求: 查询每个供应商在每个类型产品销售的top50中有多少 分析: 1.查询,以指定字段(供应商.产品类型)分组,取每个分组的前50行,查看每个供应商的数量 2.使用rank函数给每个供应商.每个类 ...

  8. android studio友盟分享demo运行报错Gradle's dependency cache may be corrupt解决方法

    gradle-wrapper.properties里修改了gradle的版本,与之前没有报错的项目gradle版本一致.

  9. ACM-ICPC 2018 徐州赛区网络预赛 C Cacti Lottery(暴力+期望)

    链接https://nanti.jisuanke.com/t/31455 思路 首先先枚举把剩下的数填入星号的情况(其实就是枚举星号的排列),这是对方所能知道的所有信息,然后对方将取八种决策中最优的情 ...

  10. 将批量指定的docker镜像打成文件

      #/bin/bash tag= img1=hub.chinacloud.com.cn/onex.dev/one-task-scheduler:$tag img2=hub.chinacloud.co ...