zoukankan      html  css  js  c++  java
  • 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>,根据实际需要选择,如有没有顺序要求。

  • 相关阅读:
    放假期间网站被挂马的解决办法
    放假期间网站被挂马的解决办法
    判断一个字符串中字母的个数(无视大小写)
    判断一个字符串中字母的个数(无视大小写)
    JSP 9 大内置对象详解
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    2019年企业数据生产力调研报告,90%的人都没看过
    2019年12月数据库流行度排行:前三甲高位收官 数据库重获增长趋势
  • 原文地址:https://www.cnblogs.com/shawnhu/p/7837804.html
Copyright © 2011-2022 走看看