递归时候每次调用自身在堆栈上要记录返回地址,而堆栈的空间很少,调用次数多了后会产生堆栈溢出,以下代码是实际项目中,通过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. iOS.KVC.setValue:forKey:

    Foundation Framework 定义了 NSObject(NSKeyValueCoding), - (void)setValue:(id)value forKey:(NSString *)k ...

  2. LibreOJ #6000. 「网络流 24 题」搭配飞行员 最大匹配

    #6000. 「网络流 24 题」搭配飞行员 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据   题目描述 ...

  3. How to Change MAC Address on Ubuntu

    1 Open Terminal.   2 Log in as root so type: sudo -i and then write your password.   3 View your cur ...

  4. 记录一次JVM调优【GC日志的分析】

    首先查看服务器版本默认信息: 修改tomcat/bin/catalina.sh,在最顶端加入JAVA_OPTS="$JAVA_OPTS -XX:+PrintGCDetails -Xloggc ...

  5. Alpha 冲刺 (1/10)

    队名 火箭少男100 组长博客 林燊大哥 作业博客 Alpha 冲鸭! 成员冲刺阶段情况 林燊(组长) 过去两天完成了哪些任务 协调各成员之间的工作,对多个目标检测及文字识别模型进行评估.实验,选取较 ...

  6. 关于流量升高导致TIME_WAIT增加,MySQL连接大量失败的问题

    有个应用就是每次都会去查一个接口,接口返回用户的信息数据,从而展现不同的页面效果.大致流程如下 应用APP(电信)-> memcache ->电信custom接口 ->master- ...

  7. 2018.11.05 NOIP模拟 规避(最短路计数)

    传送门 正难则反. 考虑计算两人相遇的方案数. 先正反跑一遍最短路计数. 然后对于一条在最短路上的边(u,v)(u,v)(u,v),如果(dis(s,u)*2<total&&di ...

  8. p1 批梯度下降算法

    (蓝色字体:批注:绿色背景:需要注意的地方:橙色背景是问题) 一,机器学习分类 二,梯度下降算法:2.1模型   2.2代价函数   2.3 梯度下降算法 一,机器学习分类 无监督学习和监督学习 无监 ...

  9. CodeForces 235E Number Challenge (莫比乌斯反演)

    题意:求,其中d(x) 表示 x 的约数个数. 析:其实是一个公式题,要知道一个结论 知道这个结论就好办了. 然后就可以解决这个问题了,优化就是记忆化gcd. 代码如下: #pragma commen ...

  10. Sprinig泛型依赖注入

    在父类中建立关系 (spring4.x以上版本) package com.spring.annotation.generic; import org.springframework.beans.fac ...