C# 使用Queue<T>代替递归算法遍历树
递归时候每次调用自身在堆栈上要记录返回地址,而堆栈的空间很少,调用次数多了后会产生堆栈溢出,以下代码是实际项目中,通过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>代替递归算法遍历树的更多相关文章
- POJ 1849 Two(遍历树)
POJ 1849 Two(遍历树) http://poj.org/problem?id=1849 题意: 有一颗n个结点的带权的无向树, 在s结点放两个机器人, 这两个机器人会把树的每条边都走一遍, ...
- Java集合的Stack、Queue、Map的遍历
Java集合的Stack.Queue.Map的遍历 在集合操作中,常常离不开对集合的遍历,对集合遍历一般来说一个foreach就搞定了,但是,对于Stack.Queue.Map类型的遍历,还是有一 ...
- lintcode :前序遍历和中序遍历树构造二叉树
解题 前序遍历和中序遍历树构造二叉树 根据前序遍历和中序遍历树构造二叉树. 样例 给出中序遍历:[1,2,3]和前序遍历:[2,1,3]. 返回如下的树: 2 / \ 1 3 注意 你可以假设树中不存 ...
- lintcode: 中序遍历和后序遍历树构造二叉树
题目 中序遍历和后序遍历树构造二叉树 根据中序遍历和后序遍历树构造二叉树 样例 给出树的中序遍历: [1,2,3] 和后序遍历: [1,3,2] 返回如下的树: 2 / \ 1 3 注意 你可 ...
- java遍历树(深度遍历和广度遍历
java遍历树如现有以下一颗树:A B B1 B11 B2 B22 C C ...
- LintCode-72.中序遍历和后序遍历树构造二叉树
中序遍历和后序遍历树构造二叉树 根据中序遍历和后序遍历树构造二叉树 注意事项 你可以假设树中不存在相同数值的节点 样例 给出树的中序遍历: [1,2,3] 和后序遍历: [1,3,2] 返回如下的树: ...
- LintCode-73.前序遍历和中序遍历树构造二叉树
前序遍历和中序遍历树构造二叉树 根据前序遍历和中序遍历树构造二叉树. 注意事项 你可以假设树中不存在相同数值的节点 样例 给出中序遍历:[1,2,3]和前序遍历:[2,1,3]. 返回如下的树: ...
- 问题:Oracle 树形遍历;结果:使用oracle进行遍历树操作
使用oracle进行遍历树操作 1:首先数据库中表必须是树形结构的 2:super_department_id 为 department_id 的父节点编号 3:以下语句的执行结果是:depart ...
- js39---组合模式,查找遍历树
/** *有这样一个需求 *有一个学校有2个班(一班,二班) *每个班级分2个小组(一班一组,一班二组,二班一组,二班二组) *学校计算机教室有限,每一个小组分着来上课. *考试的时候大家一起考 *请 ...
随机推荐
- eclipse中增加多个Tomcat
一.在eclipse中新增Tomcat,并增加在其上部署的工程 1.打开eclipse,并选择菜单中的 "Window" ---> "Show View" ...
- 记录ssh暴力破解的密码字典
之前我已经在wooyun和91ri上发表了这篇文章,今天转到51cto上... 默认的ssh日志是不带密码记录功能的,现在想把登录密码记录下来,这样就可以搜集黑客的ssh爆破字典了,从而可以反扫回去. ...
- JDK 规范目录
JDK 规范目录 1.1 Java 异常处理 2.1 JDK 之 NIO 2 WatchService.WatchKey(监控文件变化) https://mp.weixin.qq.com/s/NIn2 ...
- .core 学习文档
https://docs.microsoft.com/zh-cn/aspnet/core/razor-pages/?view=aspnetcore-2.1&tabs=visual-studio
- javascript对象bind()方法兼容处理
bind() 函数在 ECMA-262 第五版才被加入:它可能无法在所有浏览器上运行.你可以部份地在脚本开头加入以下代码,就能使它运作,让不支持的浏览器也能使用 bind() 功能 if (!Func ...
- 对团队项目的NABCD的分析
需求(N):我们的软件是面向广大想记录自己所爱动植物成长点滴的人.目前没有很好地软件,只有手机或者电脑上的笔记本和备忘录. 做法(A):我们的软件可以交流可以节约积累知识的时间,将记录从记事本中摘出来 ...
- 【Erlang】源码安装
Erlang介绍 Erlang(['ə:læŋ])是一种通用的面向并发的编程语言,它由瑞典电信设备制造商爱立信所辖的CS-Lab开发,目的是创造一种可以应对大规模并发活动的编程语言和运行环境. Erl ...
- java:static详解
1.static修饰的变量习惯称为静态变量,static修饰的方法称为静态方法,static修饰的代码块叫做静态代码块. 1)static变量 static变量也称作静态变量,静态变量和非静态变量的区 ...
- django之content_type
什么是content type:django内置的一个组件,这个组件帮忙做连表的操作.(混搭连表) 适用场景:适用于一张表与多张表同时做关联的时候.直接导入就可以使用了. 关联数据库说有的表:让我们可 ...
- Django的开始
一 浏览器相关知识 http:只有依赖一回,属于短链接,不会报错客户端的信息. 浏览器相当于一个客户端,客户端的链接 服务端:socket服务端,起服务监听客户端的请求. import socket ...