• 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>,根据实际需要选择,如有没有顺序要求。

  • 相关阅读:
    WebSocket
    betterscroll
    css font
    luckycanvas
    ios系统使用占比
    设备趋势
    高效阅读代码工具
    逻辑地址、物理地址、线性地址、虚拟地址
    怎么用抓包工具Fiddler进行弱网测试【杭州多测师_王sir】【杭州多测师】
    后端测试,服务器端测试【杭州多测师】【杭州多测师_王sir】
  • 原文地址:https://www.cnblogs.com/shawnhu/p/7837804.html
Copyright © 2020-2023  润新知