递归时候每次调用自身在堆栈上要记录返回地址,而堆栈的空间很少,调用次数多了后会产生堆栈溢出,以下代码是实际项目中,通过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>,根据实际需要选择,如有没有顺序要求。
|
请发表评论