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

public
IList<OfficeGroupNodeDto>
GetSelfAndChildOfficesByGroupId(int
groupId)
{

/// <summary>
/// 获取某个节点下特定属性的所有子孙节点
/// </summary>
/// <param name=”groupId”></param>
/// <returns></returns>

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

  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();
澳门新葡亰赌995577,    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>,根据实际需要选择,如有没有顺序要求。