• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

C#使用QueueT代替递归算法遍历树

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

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


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
C#中的接口实现多态发布时间:2022-07-13
下一篇:
C#删除字符串最后一个字符的几种方法发布时间:2022-07-13
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap